Skip to content
This repository was archived by the owner on Jul 21, 2025. It is now read-only.

Commit 6fb23b3

Browse files
committed
sync with ILSpy 5.0.2
1 parent 0d4922c commit 6fb23b3

37 files changed

+1303
-221
lines changed

ILSpy.Core/Analyzers/AnalyzerScope.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ IEnumerable<PEFile> GetReferencingModules(PEFile self, CancellationToken ct)
133133
{
134134
yield return self;
135135

136-
foreach (var assembly in AssemblyList.GetAssemblies()) {
136+
string reflectionTypeScopeName = typeScope.Name;
137+
if (typeScope.TypeParameterCount > 0)
138+
reflectionTypeScopeName += "`" + typeScope.TypeParameterCount;
139+
140+
foreach (var assembly in AssemblyList.GetAssemblies()) {
137141
ct.ThrowIfCancellationRequested();
138142
bool found = false;
139143
var module = assembly.GetPEFileOrNull();
@@ -148,7 +152,7 @@ IEnumerable<PEFile> GetReferencingModules(PEFile self, CancellationToken ct)
148152
}
149153
}
150154
}
151-
if (found && ModuleReferencesScopeType(module.Metadata, typeScope.Name, typeScope.Namespace))
155+
if (found && ModuleReferencesScopeType(module.Metadata, reflectionTypeScopeName, typeScope.Namespace))
152156
yield return module;
153157
}
154158
}

ILSpy.Core/Analyzers/Builtin/EventImplementsInterfaceAnalyzer.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,18 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
4141
}
4242

4343
IEnumerable<IEntity> AnalyzeType(IEvent analyzedEntity, ITypeDefinition type)
44-
{
45-
var token = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
46-
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
47-
if (!type.GetAllBaseTypeDefinitions()
48-
.Any(t => t.MetadataToken == token && t.ParentModule.PEFile == module))
49-
yield break;
44+
{
45+
var token = analyzedEntity.MetadataToken;
46+
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
47+
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
48+
var allTypes = type.GetAllBaseTypeDefinitions();
49+
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module))
50+
yield break;
5051

51-
foreach (var @event in type.GetEvents(options: GetMemberOptions.ReturnMemberDefinitions)) {
52-
if (InheritanceHelper.GetBaseMembers(@event, true)
53-
.Any(m => m.DeclaringTypeDefinition.MetadataToken == token && m.ParentModule.PEFile == module))
54-
yield return @event;
52+
foreach (var @event in type.Events) {
53+
var baseMembers = InheritanceHelper.GetBaseMembers(@event, true);
54+
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module))
55+
yield return @event;
5556
}
5657
}
5758

ILSpy.Core/Analyzers/Builtin/EventOverriddenByAnalyzer.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,18 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
4242

4343
IEnumerable<IEntity> AnalyzeType(IEvent analyzedEntity, ITypeDefinition type)
4444
{
45-
if (!analyzedEntity.DeclaringType.GetAllBaseTypeDefinitions()
46-
.Any(t => t.MetadataToken == analyzedEntity.DeclaringTypeDefinition.MetadataToken && t.ParentModule.PEFile == type.ParentModule.PEFile))
47-
yield break;
45+
var token = analyzedEntity.MetadataToken;
46+
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
47+
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
48+
var allTypes = type.GetAllBaseTypeDefinitions();
49+
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module))
50+
yield break;
4851

4952
foreach (var @event in type.Events) {
5053
if (!@event.IsOverride) continue;
51-
if (InheritanceHelper.GetBaseMembers(@event, false)
52-
.Any(p => p.MetadataToken == analyzedEntity.MetadataToken &&
53-
p.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile)) {
54-
yield return @event;
54+
var baseMembers = InheritanceHelper.GetBaseMembers(@event, false);
55+
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) {
56+
yield return @event;
5557
}
5658
}
5759
}

ILSpy.Core/Analyzers/Builtin/MethodImplementsInterfaceAnalyzer.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,17 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
4545

4646
IEnumerable<IEntity> AnalyzeType(IMethod analyzedEntity, ITypeDefinition type)
4747
{
48-
var token = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
49-
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
50-
if (!type.GetAllBaseTypeDefinitions()
51-
.Any(t => t.MetadataToken == token && t.ParentModule.PEFile == module))
52-
yield break;
48+
var token = analyzedEntity.MetadataToken;
49+
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
50+
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
51+
var allTypes = type.GetAllBaseTypeDefinitions();
52+
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module))
53+
yield break;
5354

54-
foreach (var method in type.GetMethods(options: GetMemberOptions.ReturnMemberDefinitions)) {
55-
if (InheritanceHelper.GetBaseMembers(method, true)
56-
.Any(m => m.DeclaringTypeDefinition.MetadataToken == token && m.ParentModule.PEFile == module))
57-
yield return method;
55+
foreach (var method in type.Methods) {
56+
var baseMembers = InheritanceHelper.GetBaseMembers(method, true);
57+
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module))
58+
yield return method;
5859
}
5960
}
6061

ILSpy.Core/Analyzers/Builtin/MethodOverriddenByAnalyzer.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,18 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
4444

4545
IEnumerable<IEntity> AnalyzeType(IMethod analyzedEntity, ITypeDefinition type)
4646
{
47-
if (!type.GetAllBaseTypeDefinitions()
48-
.Any(t => t.MetadataToken == analyzedEntity.DeclaringTypeDefinition.MetadataToken
49-
&& t.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile))
50-
yield break;
47+
var token = analyzedEntity.MetadataToken;
48+
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
49+
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
50+
var allTypes = type.GetAllBaseTypeDefinitions();
51+
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module))
52+
yield break;
5153

5254
foreach (var method in type.Methods) {
5355
if (!method.IsOverride) continue;
54-
if (InheritanceHelper.GetBaseMembers(method, false)
55-
.Any(p => p.MetadataToken == analyzedEntity.MetadataToken &&
56-
p.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile)) {
57-
yield return method;
56+
var baseMembers = InheritanceHelper.GetBaseMembers(method, false);
57+
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) {
58+
yield return method;
5859
}
5960
}
6061
}

ILSpy.Core/Analyzers/Builtin/PropertyImplementsInterfaceAnalyzer.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,17 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
4242

4343
IEnumerable<IEntity> AnalyzeType(IProperty analyzedEntity, ITypeDefinition type)
4444
{
45-
var token = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
46-
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
47-
if (!type.GetAllBaseTypeDefinitions()
48-
.Any(t => t.MetadataToken == token && t.ParentModule.PEFile == module))
49-
yield break;
45+
var token = analyzedEntity.MetadataToken;
46+
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
47+
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
48+
var allTypes = type.GetAllBaseTypeDefinitions();
49+
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module))
50+
yield break;
5051

51-
foreach (var property in type.GetProperties(options: GetMemberOptions.ReturnMemberDefinitions)) {
52-
if (InheritanceHelper.GetBaseMembers(property, true)
53-
.Any(m => m.DeclaringTypeDefinition.MetadataToken == token && m.ParentModule.PEFile == module))
54-
yield return property;
52+
foreach (var property in type.Properties) {
53+
var baseMembers = InheritanceHelper.GetBaseMembers(property, true);
54+
if (baseMembers.Any(m => m.MetadataToken == token && m.ParentModule.PEFile == module))
55+
yield return property;
5556
}
5657
}
5758

ILSpy.Core/Analyzers/Builtin/PropertyOverriddenByAnalyzer.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,18 @@ public IEnumerable<ISymbol> Analyze(ISymbol analyzedSymbol, AnalyzerContext cont
4545

4646
IEnumerable<IEntity> AnalyzeType(IProperty analyzedEntity, ITypeDefinition type)
4747
{
48-
if (!analyzedEntity.DeclaringType.GetAllBaseTypeDefinitions()
49-
.Any(t => t.MetadataToken == analyzedEntity.DeclaringTypeDefinition.MetadataToken && t.ParentModule.PEFile == type.ParentModule.PEFile))
50-
yield break;
48+
var token = analyzedEntity.MetadataToken;
49+
var declaringTypeToken = analyzedEntity.DeclaringTypeDefinition.MetadataToken;
50+
var module = analyzedEntity.DeclaringTypeDefinition.ParentModule.PEFile;
51+
var allTypes = type.GetAllBaseTypeDefinitions();
52+
if (!allTypes.Any(t => t.MetadataToken == declaringTypeToken && t.ParentModule.PEFile == module))
53+
yield break;
5154

5255
foreach (var property in type.Properties) {
5356
if (!property.IsOverride) continue;
54-
if (InheritanceHelper.GetBaseMembers(property, false)
55-
.Any(p => p.MetadataToken == analyzedEntity.MetadataToken &&
56-
p.ParentModule.PEFile == analyzedEntity.ParentModule.PEFile)) {
57-
yield return property;
57+
var baseMembers = InheritanceHelper.GetBaseMembers(property, false);
58+
if (baseMembers.Any(p => p.MetadataToken == token && p.ParentModule.PEFile == module)) {
59+
yield return property;
5860
}
5961
}
6062
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4+
// software and associated documentation files (the "Software"), to deal in the Software
5+
// without restriction, including without limitation the rights to use, copy, modify, merge,
6+
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7+
// to whom the Software is furnished to do so, subject to the following conditions:
8+
//
9+
// The above copyright notice and this permission notice shall be included in all copies or
10+
// substantial portions of the Software.
11+
//
12+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13+
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14+
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15+
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17+
// DEALINGS IN THE SOFTWARE.
18+
19+
using System;
20+
using System.Collections.Generic;
21+
using System.IO;
22+
using System.Linq;
23+
using System.Threading.Tasks;
24+
using System.Windows;
25+
using System.Windows.Input;
26+
using Avalonia.Controls;
27+
using ICSharpCode.ILSpy.Properties;
28+
using ICSharpCode.ILSpy.TreeNodes;
29+
using ICSharpCode.TreeView;
30+
using Microsoft.Win32;
31+
32+
namespace ICSharpCode.ILSpy.TextView
33+
{
34+
[ExportContextMenuEntry(Header = nameof(Resources._SaveCode), Category = nameof(Resources.Save), Icon = "Images/SaveFile.png")]
35+
sealed class SaveCodeContextMenuEntry : IContextMenuEntry
36+
{
37+
public void Execute(TextViewContext context)
38+
{
39+
Execute(context.SelectedTreeNodes);
40+
}
41+
42+
public bool IsEnabled(TextViewContext context) => true;
43+
44+
public bool IsVisible(TextViewContext context)
45+
{
46+
return CanExecute(context.SelectedTreeNodes);
47+
}
48+
49+
public static bool CanExecute(IReadOnlyList<SharpTreeNode> selectedNodes)
50+
{
51+
if (selectedNodes == null || selectedNodes.Any(n => !(n is ILSpyTreeNode)))
52+
return false;
53+
return selectedNodes.Count == 1
54+
|| (selectedNodes.Count > 1 && (selectedNodes.All(n => n is AssemblyTreeNode) || selectedNodes.All(n => n is IMemberTreeNode)));
55+
}
56+
57+
public static async Task Execute(IReadOnlyList<SharpTreeNode> selectedNodes)
58+
{
59+
var currentLanguage = MainWindow.Instance.CurrentLanguage;
60+
var textView = MainWindow.Instance.TextView;
61+
if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection)
62+
{
63+
// if there's only one treenode selected
64+
// we will invoke the custom Save logic
65+
if (await singleSelection.Save(textView))
66+
return;
67+
}
68+
else if (selectedNodes.Count > 1 && selectedNodes.All(n => n is AssemblyTreeNode))
69+
{
70+
var selectedPath = await SelectSolutionFile();
71+
72+
if (!string.IsNullOrEmpty(selectedPath))
73+
{
74+
var assemblies = selectedNodes.OfType<AssemblyTreeNode>()
75+
.Select(n => n.LoadedAssembly)
76+
.Where(a => !a.HasLoadError).ToArray();
77+
SolutionWriter.CreateSolution(textView, selectedPath, currentLanguage, assemblies);
78+
}
79+
return;
80+
}
81+
82+
// Fallback: if nobody was able to handle the request, use default behavior.
83+
// try to save all nodes to disk.
84+
var options = new DecompilationOptions() { FullDecompilation = true };
85+
textView.SaveToDisk(currentLanguage, selectedNodes.OfType<ILSpyTreeNode>(), options);
86+
}
87+
88+
/// <summary>
89+
/// Shows a File Selection dialog where the user can select the target file for the solution.
90+
/// </summary>
91+
/// <param name="path">The initial path to show in the dialog. If not specified, the 'Documents' directory
92+
/// will be used.</param>
93+
///
94+
/// <returns>The full path of the selected target file, or <c>null</c> if the user canceled.</returns>
95+
static async Task<string> SelectSolutionFile()
96+
{
97+
SaveFileDialog dlg = new SaveFileDialog();
98+
dlg.InitialFileName = "Solution.sln";
99+
dlg.Filters = new List<FileDialogFilter>()
100+
{
101+
new FileDialogFilter { Name = "Visual Studio Solution file", Extensions = { "sln" } },
102+
new FileDialogFilter { Name = "All files", Extensions = { "*"} },
103+
};
104+
105+
string filename = await dlg.ShowAsync(MainWindow.Instance);
106+
if (filename != null)
107+
{
108+
return null;
109+
}
110+
111+
string selectedPath = Path.GetDirectoryName(filename);
112+
bool directoryNotEmpty;
113+
try
114+
{
115+
directoryNotEmpty = Directory.EnumerateFileSystemEntries(selectedPath).Any();
116+
}
117+
catch (Exception e) when (e is IOException || e is UnauthorizedAccessException || e is System.Security.SecurityException)
118+
{
119+
await MessageBox.Show(
120+
"The directory cannot be accessed. Please ensure it exists and you have sufficient rights to access it.",
121+
"Solution directory not accessible",
122+
MessageBoxButton.OK, MessageBoxImage.Error);
123+
return null;
124+
}
125+
126+
if (directoryNotEmpty)
127+
{
128+
var result = await MessageBox.Show(
129+
Resources.AssemblySaveCodeDirectoryNotEmpty,
130+
Resources.AssemblySaveCodeDirectoryNotEmptyTitle,
131+
MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
132+
if (result == MessageBoxResult.No)
133+
return null; // -> abort
134+
}
135+
136+
return filename;
137+
}
138+
}
139+
}

ILSpy.Core/ILSpy.Core.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@
2727
</PropertyGroup>
2828

2929
<ItemGroup>
30-
<PackageReference Include="Avalonia" />
31-
<PackageReference Include="Avalonia.Controls.DataGrid" />
32-
<PackageReference Include="ICSharpCode.Decompiler" Version="5.0.0.4850-preview2-debug" />
30+
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
31+
<PackageReference Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersion)" />
32+
<PackageReference Include="ICSharpCode.Decompiler" Version="5.0.2.5153" />
3333
<PackageReference Include="Microsoft.DiaSymReader" Version="1.3.0" />
3434
<PackageReference Include="Microsoft.DiaSymReader.Converter.Xml" Version="1.1.0-beta1-63314-01" />
35-
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="15.8.98" />
35+
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="16.4.11" />
3636
<PackageReference Include="NuGet.Client" Version="4.2.0" />
3737
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
3838
</ItemGroup>

0 commit comments

Comments
 (0)