diff --git a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
index 3807571cf..3ed5470e6 100644
--- a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
+++ b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj
@@ -11,6 +11,10 @@
+
+
diff --git a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
index d388d459a..a1609b05a 100644
--- a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
+++ b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
@@ -81,7 +81,7 @@
-
+
diff --git a/ILSpy/Images/ILSpy.ico b/ICSharpCode.ILSpyX/MermaidDiagrammer/html/ILSpy.ico
similarity index 100%
rename from ILSpy/Images/ILSpy.ico
rename to ICSharpCode.ILSpyX/MermaidDiagrammer/html/ILSpy.ico
diff --git a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
index b966a2f49..7b15c728a 100644
--- a/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
+++ b/ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj
@@ -46,8 +46,6 @@
-
-
diff --git a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs b/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
deleted file mode 100644
index 5e2003192..000000000
--- a/ILSpy.BamlDecompiler/BamlResourceEntryNode.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2020 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-using ICSharpCode.AvalonEdit.Highlighting;
-using ICSharpCode.BamlDecompiler;
-using ICSharpCode.ILSpy;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-
-namespace ILSpy.BamlDecompiler
-{
- public sealed class BamlResourceEntryNode : ResourceEntryNode
- {
- public BamlResourceEntryNode(string key, Func data) : base(key, data)
- {
- }
-
- public override bool View(TabPageModel tabPage)
- {
- IHighlightingDefinition highlighting = null;
-
- tabPage.SupportsLanguageSwitching = false;
- tabPage.ShowTextView(textView => textView.RunWithCancellation(
- token => Task.Factory.StartNew(
- () => {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- try
- {
- LoadBaml(output, token);
- highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml");
- }
- catch (Exception ex)
- {
- output.Write(ex.ToString());
- }
- return output;
- }, token))
- .Then(output => textView.ShowNode(output, this, highlighting))
- .HandleExceptions());
- return true;
- }
-
- void LoadBaml(AvalonEditTextOutput output, CancellationToken cancellationToken)
- {
- var asm = this.Ancestors().OfType().First().LoadedAssembly;
- using var data = OpenStream();
- BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(asm.GetMetadataFileOrNull(), asm.GetAssemblyResolver());
- var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings());
- decompiler.CancellationToken = cancellationToken;
- var result = decompiler.Decompile(data);
- output.Write(result.Xaml.ToString());
- }
- }
-}
diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
deleted file mode 100644
index 151885b16..000000000
--- a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2020 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Composition;
-using System.IO;
-
-using ICSharpCode.BamlDecompiler;
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.Abstractions;
-
-namespace ILSpy.BamlDecompiler
-{
- [Export(typeof(IResourceNodeFactory))]
- [Shared]
- public sealed class BamlResourceNodeFactory : IResourceNodeFactory
- {
- public ITreeNode CreateNode(Resource resource)
- {
- if (resource.Name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase))
- return new BamlResourceEntryNode(resource.Name, resource.TryOpenStream);
- else
- return null;
- }
- }
-
- [Export(typeof(IResourceFileHandler))]
- [Shared]
- public sealed class BamlResourceFileHandler : IResourceFileHandler
- {
- public string EntryType => "Page";
- public bool CanHandle(string name, ResourceFileHandlerContext context) => name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase);
-
- public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, ResourceFileHandlerContext context)
- {
- BamlDecompilerTypeSystem typeSystem = new BamlDecompilerTypeSystem(assembly.GetMetadataFileOrNull(), assembly.GetAssemblyResolver());
- var decompiler = new XamlDecompiler(typeSystem, new BamlDecompilerSettings() {
- ThrowOnAssemblyResolveErrors = context.DecompilationOptions.DecompilerSettings.ThrowOnAssemblyResolveErrors
- });
- decompiler.CancellationToken = context.DecompilationOptions.CancellationToken;
- var result = decompiler.Decompile(stream);
- var typeDefinition = result.TypeName.HasValue ? typeSystem.MainModule.GetTypeDefinition(result.TypeName.Value.TopLevelTypeName) : null;
- if (typeDefinition != null)
- {
- fileName = WholeProjectDecompiler.SanitizeFileName(typeDefinition.ReflectionName + ".xaml");
- var partialTypeInfo = new PartialTypeInfo(typeDefinition);
- foreach (var member in result.GeneratedMembers)
- {
- partialTypeInfo.AddDeclaredMember(member);
- }
- context.AddPartialTypeInfo(partialTypeInfo);
- }
- else
- {
- fileName = Path.ChangeExtension(fileName, ".xaml");
- }
- context.AdditionalProperties.Add("Generator", "MSBuild:Compile");
- context.AdditionalProperties.Add("SubType", "Designer");
- string saveFileName = Path.Combine(context.DecompilationOptions.SaveAsProjectDirectory, fileName);
- Directory.CreateDirectory(Path.GetDirectoryName(saveFileName));
- result.Xaml.Save(saveFileName);
- return fileName;
- }
- }
-}
diff --git a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj b/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
deleted file mode 100644
index f7e3d7059..000000000
--- a/ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
- ILSpy.BamlDecompiler.Plugin
- net10.0-windows
- win-x64;win-arm64
- false
- False
- 6488064
- true
- true
-
-
-
- full
- true
- True
-
-
-
- pdbonly
- true
-
-
-
- ..\ILSpy\bin\$(Configuration)\
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs b/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs
deleted file mode 100644
index 4fbbcee16..000000000
--- a/ILSpy.BamlDecompiler/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-#region Using directives
-
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-
-#endregion
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("ILSpy.BamlDecompiler.Plugin")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ILSpy.BamlDecompiler.Plugin")]
-[assembly: AssemblyCopyright("Copyright 2011")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// This sets the default COM visibility of types in the assembly to invisible.
-// If you need to expose a type to COM, use [ComVisible(true)] on that type.
-[assembly: ComVisible(false)]
-[assembly: TargetPlatform("Windows10.0")]
-[assembly: SupportedOSPlatform("Windows7.0")]
-
-[assembly: InternalsVisibleTo("ILSpy.BamlDecompiler.Tests")]
-
-// The assembly version has following format :
-//
-// Major.Minor.Build.Revision
-//
-// You can specify all the values or you can use the default the Revision and
-// Build Numbers by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/ILSpy.BamlDecompiler/Properties/launchSettings.json b/ILSpy.BamlDecompiler/Properties/launchSettings.json
deleted file mode 100644
index 93c6637b2..000000000
--- a/ILSpy.BamlDecompiler/Properties/launchSettings.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "profiles": {
- "ILSpy.BamlDecompiler": {
- "commandName": "Executable",
- "executablePath": "$(SolutionDir)\\ILSpy\\bin\\Debug\\net6.0-windows\\ILSpy.exe",
- "commandLineArgs": "/separate"
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs b/ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs
deleted file mode 100644
index b255e7fa7..000000000
--- a/ILSpy.Tests/Analyzers/AnalyzerScopeTests.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2024 Yuriy Zatuchnyy
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Linq;
-using System.Threading.Tasks;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.CSharp.Resolver;
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpyX.Analyzers;
-
-using NUnit.Framework;
-
-namespace ICSharpCode.ILSpy.Tests.Analyzers
-{
- [TestFixture]
- public class AnalyzerScopeTests
- {
- public class TestClass
- {
-
- }
-
- [Test]
- public void WhenPublicNestedClass_ThenNotInfiniteLoop()
- {
- // Given
- ILSpyX.AssemblyList assemblyList = new ILSpyX.AssemblyList();
- var file = new PEFile(this.GetType().Assembly.Location);
- var td = file.Metadata.TypeDefinitions.First(td => td.GetFullTypeName(file.Metadata).Name == nameof(TestClass));
-
- Decompiler.Metadata.IAssemblyResolver assemblyResolver = new UniversalAssemblyResolver(null, false, null);
- ICompilation compilation = new DecompilerTypeSystem(file, assemblyResolver);
- ITypeResolveContext context = new CSharpResolver(compilation);
- var module = ((IModuleReference)file).Resolve(context) as MetadataModule;
- IEntity entity = module.GetDefinition(td);
-
- // When
- var task = Task.Run(() => {
- var target = new AnalyzerScope(assemblyList, entity);
- });
-
- var result = Task.WaitAny(new[] { task, Task.Delay(500) }); // 0.5 seconds
-
- // Then
- Assert.That(result == 0, "The constructor should complete in less than 10 seconds");
- }
-
- }
-}
diff --git a/ILSpy.Tests/Analyzers/ExportAnalyzerAttributeTests.cs b/ILSpy.Tests/Analyzers/ExportAnalyzerAttributeTests.cs
deleted file mode 100644
index c8e3af599..000000000
--- a/ILSpy.Tests/Analyzers/ExportAnalyzerAttributeTests.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2024 Andreas Weizel
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Linq;
-
-using ICSharpCode.ILSpyX.Analyzers;
-
-using NUnit.Framework;
-
-namespace ICSharpCode.ILSpy.Tests.Analyzers
-{
- [TestFixture]
- public class ExportAnalyzerAttributeTests
- {
- [Test]
- public void CollectAnalyzers()
- {
- var analyzerNames = ExportAnalyzerAttribute.GetAnnotatedAnalyzers()
- .Select(analyzer => analyzer.AnalyzerType.Name)
- .ToArray();
- Assert.That(analyzerNames.Contains("AttributeAppliedToAnalyzer"));
- Assert.That(analyzerNames.Contains("EventImplementedByAnalyzer"));
- Assert.That(analyzerNames.Contains("MethodUsedByAnalyzer"));
- Assert.That(analyzerNames.Contains("PropertyOverriddenByAnalyzer"));
- Assert.That(analyzerNames.Contains("TypeInstantiatedByAnalyzer"));
- }
- }
-}
diff --git a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs
deleted file mode 100644
index a7077bcd3..000000000
--- a/ILSpy.Tests/Analyzers/MemberImplementsInterfaceAnalyzerTests.cs
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (c) 2020 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.IO;
-using System.Linq;
-using System.Reflection.Metadata;
-using System.Reflection.PortableExecutable;
-
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.Decompiler.TypeSystem.Implementation;
-using ICSharpCode.ILSpyX.Analyzers;
-using ICSharpCode.ILSpyX.Analyzers.Builtin;
-
-using NSubstitute;
-
-using NUnit.Framework;
-
-namespace ICSharpCode.ILSpy.Tests.Analyzers
-{
- [TestFixture]
- public class MemberImplementsInterfaceAnalyzerTests
- {
- static readonly SymbolKind[] ValidSymbolKinds = { SymbolKind.Event, SymbolKind.Indexer, SymbolKind.Method, SymbolKind.Property };
- static readonly SymbolKind[] InvalidSymbolKinds =
- Enum.GetValues(typeof(SymbolKind)).Cast().Except(ValidSymbolKinds).ToArray();
-
- static readonly TypeKind[] ValidTypeKinds = { TypeKind.Class, TypeKind.Struct };
- static readonly TypeKind[] InvalidTypeKinds = Enum.GetValues(typeof(TypeKind)).Cast().Except(ValidTypeKinds).ToArray();
-
- private ICompilation testAssembly;
-
- [OneTimeSetUp]
- public void Setup()
- {
- string fileName = GetType().Assembly.Location;
-
- using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
- {
- var module = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, MetadataReaderOptions.None);
-
- testAssembly = new SimpleCompilation(module.WithOptions(TypeSystemOptions.Default), MinimalCorlib.Instance);
- }
- }
-
- [Test]
- public void VerifyDoesNotShowForNoSymbol()
- {
- // Arrange
- var analyzer = new MemberImplementsInterfaceAnalyzer();
-
- // Act
- var shouldShow = analyzer.Show(symbol: null);
-
- // Assert
- Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for no symbol");
- }
-
- [Test]
- [TestCaseSource(nameof(InvalidSymbolKinds))]
- public void VerifyDoesNotShowForNonMembers(SymbolKind symbolKind)
- {
- // Arrange
- var symbolMock = Substitute.For();
- symbolMock.SymbolKind.Returns(symbolKind);
- var analyzer = new MemberImplementsInterfaceAnalyzer();
-
- // Act
- var shouldShow = analyzer.Show(symbolMock);
-
- // Assert
- Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}'");
- }
-
- [Test]
- [TestCaseSource(nameof(ValidSymbolKinds))]
- public void VerifyDoesNotShowForStaticMembers(SymbolKind symbolKind)
- {
- // Arrange
- var memberMock = SetupMemberMock(symbolKind, TypeKind.Unknown, isStatic: true);
- var analyzer = new MemberImplementsInterfaceAnalyzer();
-
- // Act
- var shouldShow = analyzer.Show(memberMock);
-
- // Assert
- Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for static symbol '{symbolKind}'");
- }
-
- [Test]
- [Pairwise]
- public void VerifyDoesNotShowForUnsupportedTypes(
- [ValueSource(nameof(ValidSymbolKinds))] SymbolKind symbolKind,
- [ValueSource(nameof(InvalidTypeKinds))] TypeKind typeKind)
- {
- // Arrange
- var memberMock = SetupMemberMock(symbolKind, typeKind, isStatic: true);
- var analyzer = new MemberImplementsInterfaceAnalyzer();
-
- // Act
- var shouldShow = analyzer.Show(memberMock);
-
- // Assert
- Assert.That(!shouldShow, $"The analyzer will be unexpectedly shown for symbol '{symbolKind}' and '{typeKind}'");
- }
-
- [Test]
- [Pairwise]
- public void VerifyShowsForSupportedTypes(
- [ValueSource(nameof(ValidSymbolKinds))] SymbolKind symbolKind,
- [ValueSource(nameof(ValidTypeKinds))] TypeKind typeKind)
- {
- // Arrange
- var memberMock = SetupMemberMock(symbolKind, typeKind, isStatic: false);
- var analyzer = new MemberImplementsInterfaceAnalyzer();
-
- // Act
- var shouldShow = analyzer.Show(memberMock);
-
- // Assert
- Assert.That(shouldShow, $"The analyzer will not be shown for symbol '{symbolKind}' and '{typeKind}'");
- }
-
- [Test]
- public void VerifyReturnsOnlyInterfaceMembers()
- {
- // Arrange
- var symbol = SetupSymbolForAnalysis(typeof(TestClass), nameof(TestClass.TestMethod));
- var analyzer = new MemberImplementsInterfaceAnalyzer();
-
- // Act
- var results = analyzer.Analyze(symbol, new AnalyzerContext() { AssemblyList = new ILSpyX.AssemblyList(), Language = new CSharpLanguage() });
-
- // Assert
- Assert.That(results, Is.Not.Null);
- Assert.That(results.Count(), Is.EqualTo(1));
- var result = results.FirstOrDefault() as IMethod;
- Assert.That(result, Is.Not.Null);
- Assert.That(result.DeclaringTypeDefinition, Is.Not.Null);
- Assert.That(result.DeclaringTypeDefinition.Kind, Is.EqualTo(TypeKind.Interface));
- Assert.That(result.DeclaringTypeDefinition.Name, Is.EqualTo(nameof(ITestInterface)));
- }
-
- private ISymbol SetupSymbolForAnalysis(Type type, string methodName)
- {
- var typeDefinition = testAssembly.FindType(type).GetDefinition();
- return typeDefinition.Methods.First(m => m.Name == methodName);
- }
-
- private static IMember SetupMemberMock(SymbolKind symbolKind, TypeKind typeKind, bool isStatic)
- {
- var memberMock = Substitute.For();
- memberMock.SymbolKind.Returns(symbolKind);
- memberMock.DeclaringTypeDefinition.Kind.Returns(typeKind);
- memberMock.IsStatic.Returns(isStatic);
- return memberMock;
- }
-
- private interface ITestInterface
- {
- void TestMethod();
- }
-
- private class BaseClass
- {
- public virtual void TestMethod() => throw new NotImplementedException();
- }
-
- private class TestClass : BaseClass, ITestInterface
- {
- public override void TestMethod() => throw new NotImplementedException();
- }
- }
-}
diff --git a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs
deleted file mode 100644
index c58cf41a9..000000000
--- a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.Analyzers;
-using ICSharpCode.ILSpyX.Analyzers.Builtin;
-
-using NUnit.Framework;
-
-namespace ICSharpCode.ILSpy.Tests.Analyzers
-{
- [TestFixture]
- public class MethodUsesAnalyzerTests
- {
- AssemblyList assemblyList;
- CSharpLanguage language;
- LoadedAssembly testAssembly;
- ICompilation testAssemblyTypeSystem;
- ITypeDefinition typeDefinition;
-
- [OneTimeSetUp]
- public void Setup()
- {
- assemblyList = new AssemblyList();
- testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location);
- assemblyList.OpenAssembly(typeof(void).Assembly.Location);
- testAssemblyTypeSystem = testAssembly.GetTypeSystemOrNull();
- language = new CSharpLanguage();
- typeDefinition = testAssemblyTypeSystem.FindType(typeof(TestCases.Main.MainAssembly)).GetDefinition();
- }
-
- [Test]
- public void MainAssemblyUsesSystemStringEmpty()
- {
- var context = new AnalyzerContext { AssemblyList = assemblyList, Language = language };
- IMethod symbol = typeDefinition.Methods.First(m => m.Name == "UsesSystemStringEmpty");
-
- var results = new MethodUsesAnalyzer().Analyze(symbol, context).ToList();
-
- Assert.That(results.Count == 1);
- var field = results.Single() as IField;
- Assert.That(field, Is.Not.Null);
- Assert.That(!field.MetadataToken.IsNil);
- Assert.That("System.String.Empty", Is.EqualTo(field.FullName));
- }
- }
-}
diff --git a/ILSpy.Tests/Analyzers/TestCases/MainAssembly.cs b/ILSpy.Tests/Analyzers/TestCases/MainAssembly.cs
deleted file mode 100644
index b9228310b..000000000
--- a/ILSpy.Tests/Analyzers/TestCases/MainAssembly.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ICSharpCode.ILSpy.Tests.Analyzers.TestCases.Main
-{
- class MainAssembly
- {
- public string UsesSystemStringEmpty()
- {
- return string.Empty;
- }
-
- public int UsesInt32()
- {
- return int.Parse("1234");
- }
- }
-}
diff --git a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs
deleted file mode 100644
index 637165e8d..000000000
--- a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2020 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Linq;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.Analyzers;
-using ICSharpCode.ILSpyX.Analyzers.Builtin;
-
-using NUnit.Framework;
-
-namespace ICSharpCode.ILSpy.Tests.Analyzers
-{
- [TestFixture]
- public class TypeUsedByAnalyzerTests
- {
- AssemblyList assemblyList;
- CSharpLanguage language;
- LoadedAssembly testAssembly;
- ICompilation testAssemblyTypeSystem;
-
- [OneTimeSetUp]
- public void Setup()
- {
- assemblyList = new AssemblyList();
- testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location);
- testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetMetadataFileOrNull(), testAssembly.GetAssemblyResolver());
- language = new CSharpLanguage();
- }
-
- [Test]
- public void SystemInt32UsedByMainAssembly()
- {
- var context = new AnalyzerContext { AssemblyList = assemblyList, Language = language };
- var symbol = testAssemblyTypeSystem.FindType(typeof(int)).GetDefinition();
-
- var results = new TypeUsedByAnalyzer().Analyze(symbol, context).ToList();
-
- Assert.That(results, Is.Not.Empty);
- var method = results.OfType().SingleOrDefault(m => m.FullName == "ICSharpCode.ILSpy.Tests.Analyzers.TestCases.Main.MainAssembly.UsesInt32");
- Assert.That(method, Is.Not.Null);
- Assert.That(!method.MetadataToken.IsNil);
- }
- }
-}
diff --git a/ILSpy.Tests/BitmapContainer.resources b/ILSpy.Tests/BitmapContainer.resources
deleted file mode 100644
index d50495a74..000000000
Binary files a/ILSpy.Tests/BitmapContainer.resources and /dev/null differ
diff --git a/ILSpy.Tests/CommandLineArgumentsTests.cs b/ILSpy.Tests/CommandLineArgumentsTests.cs
deleted file mode 100644
index efd44a8d9..000000000
--- a/ILSpy.Tests/CommandLineArgumentsTests.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-using System;
-
-using AwesomeAssertions;
-
-using ICSharpCode.ILSpy.AppEnv;
-
-using NUnit.Framework;
-
-namespace ICSharpCode.ILSpy.Tests
-{
- [TestFixture]
- public class CommandLineArgumentsTests
- {
- [Test]
- public void VerifyEmptyArgumentsArray()
- {
- var cmdLineArgs = CommandLineArguments.Create(new string[] { });
-
- cmdLineArgs.AssembliesToLoad.Should().BeEmpty();
- cmdLineArgs.SingleInstance.Should().BeNull();
- cmdLineArgs.NavigateTo.Should().BeNull();
- cmdLineArgs.Search.Should().BeNull();
- cmdLineArgs.Language.Should().BeNull();
- cmdLineArgs.NoActivate.Should().BeFalse();
- cmdLineArgs.ConfigFile.Should().BeNull();
- }
-
- [Test]
- public void VerifyHelpOption()
- {
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--help" });
- cmdLineArgs.ArgumentsParser.IsShowingInformation.Should().BeTrue();
- }
-
- [Test]
- public void VerifyForceNewInstanceOption()
- {
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--newinstance" });
- cmdLineArgs.SingleInstance.Should().NotBeNull();
- cmdLineArgs.SingleInstance.Value.Should().BeFalse();
- }
-
- [Test]
- public void VerifyNavigateToOption()
- {
- const string navigateTo = "MyNamespace.MyClass";
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--navigateto", navigateTo });
- cmdLineArgs.NavigateTo.Should().Be(navigateTo);
- }
-
- [Test]
- public void VerifyNavigateToOption_NoneTest_Matching_VSAddin()
- {
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--navigateto:none" });
- cmdLineArgs.NavigateTo.Should().Be("none");
- }
-
- [Test]
- public void VerifyCaseSensitivityOfOptionsDoesntThrow()
- {
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--navigateTo:none" });
-
- cmdLineArgs.ArgumentsParser.RemainingArguments.Count.Should().Be(1);
- }
-
- [Test]
- public void VerifySearchOption()
- {
- const string searchWord = "TestContainers";
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--search", searchWord });
- cmdLineArgs.Search.Should().Be(searchWord);
- }
-
- [Test]
- public void VerifyLanguageOption()
- {
- const string language = "csharp";
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--language", language });
- cmdLineArgs.Language.Should().Be(language);
- }
-
- [Test]
- public void VerifyConfigOption()
- {
- const string configFile = "myilspyoptions.xml";
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--config", configFile });
- cmdLineArgs.ConfigFile.Should().Be(configFile);
- }
-
- [Test]
- public void VerifyNoActivateOption()
- {
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "--noactivate" });
- cmdLineArgs.NoActivate.Should().BeTrue();
- }
-
- [Test]
- public void MultipleAssembliesAsArguments()
- {
- var cmdLineArgs = CommandLineArguments.Create(new string[] { "assembly1", "assembly2", "assembly3" });
- cmdLineArgs.AssembliesToLoad.Count.Should().Be(3);
- }
-
- [Test]
- public void PassAtFileArguments()
- {
- string filepath = System.IO.Path.GetTempFileName();
-
- System.IO.File.WriteAllText(filepath, "assembly1\r\nassembly2\r\nassembly3\r\n--newinstance\r\n--noactivate");
-
- var cmdLineArgs = CommandLineArguments.Create(new string[] { $"@{filepath}" });
-
- try
- {
- System.IO.File.Delete(filepath);
- }
- catch (Exception)
- {
- }
-
- cmdLineArgs.SingleInstance.Should().NotBeNull();
- cmdLineArgs.SingleInstance.Value.Should().BeFalse();
- cmdLineArgs.NoActivate.Should().BeTrue();
- cmdLineArgs.AssembliesToLoad.Count.Should().Be(3);
- }
- }
-}
diff --git a/ILSpy.Tests/ILSpy.Tests.csproj b/ILSpy.Tests/ILSpy.Tests.csproj
deleted file mode 100644
index 63ede48c1..000000000
--- a/ILSpy.Tests/ILSpy.Tests.csproj
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
- true
- true
-
-
-
- net11.0-windows
- false
- win-x64
- win-arm64
- Exe
-
- True
-
- $(NoWarn);1701;1702;1705,67,169,1058,728,1720,649,168,251
-
- false
-
- ICSharpCode.ILSpy.Tests
- True
-
- True
- ..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk
-
-
-
- full
- true
-
-
-
- pdbonly
- true
-
-
-
- TRACE;DEBUG;NET46;ROSLYN;CS60;CS70
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ResXCodeGenerator
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ILSpy.Tests/Icon.ico b/ILSpy.Tests/Icon.ico
deleted file mode 100644
index 5d06b9f28..000000000
Binary files a/ILSpy.Tests/Icon.ico and /dev/null differ
diff --git a/ILSpy.Tests/IconContainer.resx b/ILSpy.Tests/IconContainer.resx
deleted file mode 100644
index 842140e25..000000000
--- a/ILSpy.Tests/IconContainer.resx
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
-
- Icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
\ No newline at end of file
diff --git a/ILSpy.Tests/ResourceReaderWriterTests.cs b/ILSpy.Tests/ResourceReaderWriterTests.cs
deleted file mode 100644
index bc15fa8bf..000000000
--- a/ILSpy.Tests/ResourceReaderWriterTests.cs
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (c) 2023 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Drawing;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Xml.Linq;
-using System.Xml.XPath;
-
-using ICSharpCode.Decompiler.Util;
-
-using NUnit.Framework;
-using NUnit.Framework.Internal;
-
-using TomsToolbox.Essentials;
-
-namespace ICSharpCode.ILSpy.Tests
-{
- [TestFixture]
- public class ResourceReaderWriterTests
- {
- const string winFormsAssemblyName = ", System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
- const string msCorLibAssemblyName = ", mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
- const string drawingAssemblyName = ", System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
-
- [Serializable]
- public class SerializableClass
- {
- public string Name { get; set; }
- public int Age { get; set; }
- }
-
- static readonly object[][] testWriteCases = {
- new object[] { "Decimal", 1.0m, "1.0", "System.Decimal" + msCorLibAssemblyName },
- new object[] { "TimeSpan", TimeSpan.FromSeconds(42), "00:00:42", "System.TimeSpan" + msCorLibAssemblyName },
- new object[] { "DateTime", DateTime.Parse("06/18/2023 21:36:30", CultureInfo.InvariantCulture), "06/18/2023 21:36:30", "System.DateTime" + msCorLibAssemblyName },
- };
-
- static readonly object[][] testReadCases = {
- new object[] { "Decimal", 1.0m },
- new object[] { "TimeSpan", TimeSpan.FromSeconds(42) },
- new object[] { "DateTime", DateTime.Parse("06/18/2023 21:36:30", CultureInfo.InvariantCulture) },
- };
-
- static Stream GetResource(string fileName)
- {
- return typeof(ResourceReaderWriterTests).Assembly.GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + "." + fileName);
- }
-
- static MemoryStream ProduceResourcesTestFile(string name, T value)
- {
- var ms = new MemoryStream();
- var writer = new System.Resources.ResourceWriter(ms);
- writer.AddResource(name, value);
- writer.Generate();
- ms.Position = 0;
- return ms;
- }
-
- static XElement ProduceResXTest(string name, T value)
- {
- using var ms = new MemoryStream();
- var writer = new Decompiler.Util.ResXResourceWriter(ms);
- writer.AddResource(name, value);
- writer.Generate();
- ms.Position = 0;
- var doc = XDocument.Load(ms);
- return doc.XPathSelectElement(".//data");
- }
-
- [TestCase("Null", null)]
- [TestCase("String", "Hello World!")]
- [TestCase("Char", 'A')]
- [TestCase("Bool", true)]
- [TestCase("Bool", false)]
- [TestCase("Byte", (byte)1)]
- [TestCase("SByte", (sbyte)-1)]
- [TestCase("Int16", (short)1)]
- [TestCase("UInt16", (ushort)1)]
- [TestCase("Int32", 1)]
- [TestCase("UInt32", (uint)1)]
- [TestCase("Int64", (long)1)]
- [TestCase("UInt64", (ulong)1)]
- [TestCase("Single", 1.0f)]
- [TestCase("Double", 1.0d)]
- [TestCase("Bytes", new byte[] { 42, 43, 44 })]
- [TestCaseSource(nameof(testReadCases))]
- public void Read(string name, object value)
- {
- using var testFile = ProduceResourcesTestFile(name, value);
- using var reader = new ResourcesFile(testFile);
- var items = reader.ToArray();
- Assert.That(items.Length, Is.EqualTo(1));
- Assert.That(items[0].Key, Is.EqualTo(name));
- Assert.That(items[0].Value, Is.EqualTo(value));
- }
-
- [TestCase("Null", null, null, "System.Resources.ResXNullRef" + winFormsAssemblyName)]
- [TestCase("String", "Hello World!", "Hello World!", null)]
- [TestCase("Bool", true, "True", "System.Boolean" + msCorLibAssemblyName)]
- [TestCase("Bool", false, "False", "System.Boolean" + msCorLibAssemblyName)]
- [TestCase("Char", 'A', "A", "System.Char" + msCorLibAssemblyName)]
- [TestCase("Byte", (byte)1, "1", "System.Byte" + msCorLibAssemblyName)]
- [TestCase("SByte", (sbyte)-1, "-1", "System.SByte" + msCorLibAssemblyName)]
- [TestCase("Int16", (short)1, "1", "System.Int16" + msCorLibAssemblyName)]
- [TestCase("UInt16", (ushort)1, "1", "System.UInt16" + msCorLibAssemblyName)]
- [TestCase("Int32", 1, "1", "System.Int32" + msCorLibAssemblyName)]
- [TestCase("UInt32", (uint)1, "1", "System.UInt32" + msCorLibAssemblyName)]
- [TestCase("Int64", (long)1, "1", "System.Int64" + msCorLibAssemblyName)]
- [TestCase("UInt64", (ulong)1, "1", "System.UInt64" + msCorLibAssemblyName)]
- [TestCase("Single", 1.0f, "1", "System.Single" + msCorLibAssemblyName)]
- [TestCase("Double", 1.0d, "1", "System.Double" + msCorLibAssemblyName)]
- [TestCaseSource(nameof(testWriteCases))]
- public void Write(string name, object value, string serializedValue, string typeName)
- {
- var element = ProduceResXTest(name, value);
- Assert.That(element.Attribute("name")?.Value, Is.EqualTo(name));
- if (typeName != null)
- {
- Assert.That(element.Attribute("type")?.Value, Is.EqualTo(typeName));
- }
- var v = element.Element("value");
- Assert.That(v, Is.Not.Null);
- Assert.That(v.IsEmpty ? serializedValue == null : v.Value == serializedValue);
- }
-
- [Test]
- public void ResXSerializableClassIsRejected()
- {
- Assert.Throws(
- () => ProduceResXTest("Serial", new SerializableClass { Name = "Hugo", Age = 42 })
- );
- }
-
- [Test]
- public void BitmapIsResourceSerializedObject()
- {
- Stream stream = typeof(ResourceReaderWriterTests).Assembly
- .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
- using var reader = new ResourcesFile(stream);
- var items = reader.ToArray();
- Assert.That(items.Length, Is.EqualTo(3));
- var item = items.FirstOrDefault(i => i.Key == "Bitmap");
- Assert.That(item.Key, Is.Not.Null);
- Assert.That(item.Value, Is.InstanceOf());
- var rso = (ResourceSerializedObject)item.Value;
- Assert.That(rso.TypeName, Is.Null);
- }
-
- [Test]
- public void ByteArrayIsSupported()
- {
- Stream stream = typeof(ResourceReaderWriterTests).Assembly
- .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
- using var reader = new ResourcesFile(stream);
- var items = reader.ToArray();
- Assert.That(items.Length, Is.EqualTo(3));
- var item = items.FirstOrDefault(i => i.Key == "Byte[]");
- Assert.That(item.Key, Is.Not.Null);
- Assert.That(item.Value, Is.InstanceOf());
- byte[] array = (byte[])item.Value;
- Assert.That(array.Length, Is.EqualTo(3));
- Assert.That(array[0], Is.EqualTo(42));
- Assert.That(array[1], Is.EqualTo(43));
- Assert.That(array[2], Is.EqualTo(44));
- }
-
- [Test]
- public void MemoryStreamIsSupported()
- {
- Stream stream = typeof(ResourceReaderWriterTests).Assembly
- .GetManifestResourceStream(typeof(ResourceReaderWriterTests).Namespace + ".Test.resources");
- using var reader = new ResourcesFile(stream);
- var items = reader.ToArray();
- Assert.That(items.Length, Is.EqualTo(3));
- var item = items.FirstOrDefault(i => i.Key == "MemoryStream");
- Assert.That(item.Key, Is.Not.Null);
- Assert.That(item.Value, Is.InstanceOf());
- }
-
- [Test]
- public void IconDataCanBeDeserializedFromResX()
- {
- // Uses new serialization format
- var resourcesStream = GetResource("IconContainer.resources");
- var reader = new ResourcesFile(resourcesStream);
- var item = reader.Single();
- Assert.That(item.Key, Is.EqualTo("Icon"));
- Assert.That(item.Value, Is.InstanceOf());
- var rso = (ResourceSerializedObject)item.Value;
- var xml = ProduceResXTest("Icon", rso);
- Assert.That(xml.GetAttribute("name"), Is.EqualTo("Icon"));
- Assert.That(xml.GetAttribute("type"), Is.EqualTo("System.Drawing.Icon" + drawingAssemblyName));
- Assert.That(xml.GetAttribute("mimetype"), Is.EqualTo("application/x-microsoft.net.object.bytearray.base64"));
- var base64Icon = xml.Element("value").Value;
- using var memory = new MemoryStream(Convert.FromBase64String(base64Icon));
- new Icon(memory);
- }
-
- [Test]
- public void BitmapDataCanBeDeserializedFromResX()
- {
- // Uses old serialization format
- var resourcesStream = GetResource("BitmapContainer.resources");
- var reader = new ResourcesFile(resourcesStream);
- var item = reader.Single(x => x.Key == "Image1");
- Assert.That(item.Value, Is.InstanceOf());
- var rso = (ResourceSerializedObject)item.Value;
- var xml = ProduceResXTest("Image1", rso);
- Assert.That(xml.GetAttribute("name"), Is.EqualTo("Image1"));
- Assert.That(xml.GetAttribute("type"), Is.Null);
- Assert.That(xml.GetAttribute("mimetype"), Is.EqualTo("application/x-microsoft.net.object.binary.base64"));
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy.Tests/Test.resources b/ILSpy.Tests/Test.resources
deleted file mode 100644
index 375a8c249..000000000
Binary files a/ILSpy.Tests/Test.resources and /dev/null differ
diff --git a/ILSpy.Tests/UpdateServiceTests.cs b/ILSpy.Tests/UpdateServiceTests.cs
deleted file mode 100644
index 599facc17..000000000
--- a/ILSpy.Tests/UpdateServiceTests.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-
-using AwesomeAssertions;
-
-using ICSharpCode.ILSpy.Updates;
-
-using NUnit.Framework;
-
-namespace ICSharpCode.ILSpy.Tests;
-
-[TestFixture]
-public class UpdateServiceTests
-{
- [Test]
- public async Task GetLatestVersionAsync_UsesReleaseTag_WhenReleaseTagIsPresent()
- {
- const string xml = """
-
-
- 10.0.0.0
- v10.0
- https://example.com/ignored.zip
-
-
- """;
-
- using var client = new HttpClient(new StubHttpMessageHandler(xml));
-
- var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
-
- result.Version.Should().Be(new Version(10, 0, 0, 0));
- result.DownloadUrl.Should().Be("https://github.com/icsharpcode/ILSpy/releases/tag/v10.0");
- }
-
- [Test]
- public async Task GetLatestVersionAsync_ReturnsNullDownloadUrl_WhenReleaseTagContainsPathTraversalAttempt()
- {
- const string xml = """
-
-
- 10.0.0.0
- ../malicious
- https://example.com/ignored.zip
-
-
- """;
-
- using var client = new HttpClient(new StubHttpMessageHandler(xml));
-
- var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
-
- result.Version.Should().Be(new Version(10, 0, 0, 0));
- result.DownloadUrl.Should().BeNull();
- }
-
- [Test]
- public async Task GetLatestVersionAsync_UsesDownloadUrl_WhenReleaseTagIsMissing()
- {
- const string xml = """
-
-
- 10.0.0.0
- https://github.com/icsharpcode/ILSpy/releases/tag/v10.0
-
-
- """;
-
- using var client = new HttpClient(new StubHttpMessageHandler(xml));
-
- var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
-
- result.Version.Should().Be(new Version(10, 0, 0, 0));
- result.DownloadUrl.Should().Be("https://github.com/icsharpcode/ILSpy/releases/tag/v10.0");
- }
-
- [Test]
- public async Task GetLatestVersionAsync_UsesDownloadUrl_ButFailsBecauseBaseUrlDoesntMatch()
- {
- const string xml = """
-
-
- 10.0.0.0
- https://example.com/ilspy.zip
-
-
- """;
-
- using var client = new HttpClient(new StubHttpMessageHandler(xml));
-
- var result = await UpdateService.GetLatestVersionAsync(client, new Uri("https://example.com/updates.xml"));
-
- result.Version.Should().Be(new Version(10, 0, 0, 0));
- result.DownloadUrl.Should().BeNull();
- }
-
- sealed class StubHttpMessageHandler(string responseContent) : HttpMessageHandler
- {
- protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
- {
- return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) {
- Content = new StringContent(responseContent)
- });
- }
- }
-}
diff --git a/ILSpy.sln b/ILSpy.sln
index cc84420d0..7b24b46b1 100644
--- a/ILSpy.sln
+++ b/ILSpy.sln
@@ -1,6 +1,7 @@
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
-VisualStudioVersion = 18.4.11620.152 stable
+VisualStudioVersion = 18.4.11620.152
MinimumVisualStudioVersion = 15.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}"
ProjectSection(SolutionItems) = preProject
@@ -9,22 +10,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E7
doc\IntPtr.txt = doc\IntPtr.txt
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler", "ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj", "{984CC812-9470-4A13-AFF9-CC44068D666C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.Tests", "ICSharpCode.Decompiler.Tests\ICSharpCode.Decompiler.Tests.csproj", "{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{F32EBCC8-0E53-4421-867E-05B3D6E10C70}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler", "ILSpy.BamlDecompiler\ILSpy.BamlDecompiler.csproj", "{A6BAD2BA-76BA-461C-8B6D-418607591247}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.BamlDecompiler.Tests", "ILSpy.BamlDecompiler.Tests\ILSpy.BamlDecompiler.Tests.csproj", "{1169E6D1-1899-43D4-A500-07CE4235B388}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Tests", "ILSpy.Tests\ILSpy.Tests.csproj", "{B51C6636-B8D1-4200-9869-08F2689DE6C2}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.ReadyToRun", "ILSpy.ReadyToRun\ILSpy.ReadyToRun.csproj", "{0313F581-C63B-43BB-AA9B-07615DABD8A3}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.ILSpyCmd", "ICSharpCode.ILSpyCmd\ICSharpCode.ILSpyCmd.csproj", "{743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.PowerShell", "ICSharpCode.Decompiler.PowerShell\ICSharpCode.Decompiler.PowerShell.csproj", "{50060E0C-FA25-41F4-B72F-8490324EC9F0}"
@@ -50,10 +39,6 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1E85EFF9-E370-4683-83E4-8A3D063FF791}.Release|Any CPU.Build.0 = Release|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -62,26 +47,6 @@ Global
{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|Any CPU.Build.0 = Release|Any CPU
- {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F32EBCC8-0E53-4421-867E-05B3D6E10C70}.Release|Any CPU.Build.0 = Release|Any CPU
- {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A6BAD2BA-76BA-461C-8B6D-418607591247}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A6BAD2BA-76BA-461C-8B6D-418607591247}.Release|Any CPU.Build.0 = Release|Any CPU
- {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1169E6D1-1899-43D4-A500-07CE4235B388}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1169E6D1-1899-43D4-A500-07CE4235B388}.Release|Any CPU.Build.0 = Release|Any CPU
- {B51C6636-B8D1-4200-9869-08F2689DE6C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B51C6636-B8D1-4200-9869-08F2689DE6C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.Build.0 = Release|Any CPU
- {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0313F581-C63B-43BB-AA9B-07615DABD8A3}.Release|Any CPU.Build.0 = Release|Any CPU
{743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/ILSpy/AboutPage.cs b/ILSpy/AboutPage.cs
deleted file mode 100644
index 09b9c8496..000000000
--- a/ILSpy/AboutPage.cs
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Composition;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
-using System.Windows.Input;
-using System.Windows.Navigation;
-
-using ICSharpCode.AvalonEdit.Rendering;
-using ICSharpCode.Decompiler;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.Themes;
-using ICSharpCode.ILSpy.Updates;
-using ICSharpCode.ILSpy.ViewModels;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._Help), Header = nameof(Resources._About), MenuOrder = 99999)]
- [Shared]
- public sealed class AboutPage : SimpleCommand
- {
- readonly SettingsService settingsService;
- readonly IEnumerable aboutPageAdditions;
-
- public AboutPage(SettingsService settingsService, IEnumerable aboutPageAdditions)
- {
- this.settingsService = settingsService;
- this.aboutPageAdditions = aboutPageAdditions;
- MessageBus.Subscribers += (_, e) => ShowAboutPage(e.TabPage);
- }
-
- public override void Execute(object parameter)
- {
- MessageBus.Send(this, new NavigateToEventArgs(new RequestNavigateEventArgs(new Uri("resource://aboutpage"), null), inNewTabPage: true));
- }
-
- private void ShowAboutPage(TabPageModel tabPage)
- {
- tabPage.ShowTextView(Display);
- }
-
- private void Display(DecompilerTextView textView)
- {
- AvalonEditTextOutput output = new AvalonEditTextOutput() {
- Title = Resources.About,
- EnableHyperlinks = true
- };
- output.WriteLine(Resources.ILSpyVersion + DecompilerVersionInfo.FullVersionWithCommitHash);
-
- string prodVersion = GetDotnetProductVersion();
- output.WriteLine(Resources.NETFrameworkVersion + prodVersion);
-
- output.AddUIElement(
- delegate {
- var stackPanel = new StackPanel {
- HorizontalAlignment = HorizontalAlignment.Center,
- Orientation = Orientation.Horizontal
- };
- if (UpdateService.LatestAvailableVersion == null)
- {
- AddUpdateCheckButton(stackPanel, textView);
- }
- else
- {
- // we already retrieved the latest version sometime earlier
- ShowAvailableVersion(UpdateService.LatestAvailableVersion, stackPanel);
- }
- var checkBox = new CheckBox {
- Margin = new Thickness(4),
- Content = Resources.AutomaticallyCheckUpdatesEveryWeek
- };
-
- var settings = settingsService.GetSettings();
- checkBox.SetBinding(ToggleButton.IsCheckedProperty, new Binding("AutomaticUpdateCheckEnabled") { Source = settings });
- return new StackPanel {
- Margin = new Thickness(0, 4, 0, 0),
- Cursor = Cursors.Arrow,
- Children = { stackPanel, checkBox }
- };
- });
- output.WriteLine();
-
- foreach (var plugin in aboutPageAdditions)
- plugin.Write(output);
- output.WriteLine();
- output.Address = new Uri("resource://AboutPage");
- using (Stream s = typeof(AboutPage).Assembly.GetManifestResourceStream(typeof(AboutPage), Resources.ILSpyAboutPageTxt))
- {
- using (StreamReader r = new StreamReader(s))
- {
- while (r.ReadLine() is { } line)
- {
- output.WriteLine(line);
- }
- }
- }
- output.AddVisualLineElementGenerator(new MyLinkElementGenerator("MIT License", "resource:license.txt"));
- output.AddVisualLineElementGenerator(new MyLinkElementGenerator("third-party notices", "resource:third-party-notices.txt"));
- textView.ShowText(output);
- }
-
- private static string GetDotnetProductVersion()
- {
- // In case of AOT .Location is null, we need a fallback for that
- string assemblyLocation = typeof(Uri).Assembly.Location;
-
- if (!String.IsNullOrWhiteSpace(assemblyLocation))
- {
- return System.Diagnostics.FileVersionInfo.GetVersionInfo(assemblyLocation).ProductVersion;
- }
- else
- {
- var version = typeof(Object).Assembly.GetName().Version;
- if (version != null)
- {
- return version.ToString();
- }
- }
-
- return "UNKNOWN";
- }
-
- sealed class MyLinkElementGenerator : LinkElementGenerator
- {
- readonly Uri uri;
-
- public MyLinkElementGenerator(string matchText, string url) : base(new Regex(Regex.Escape(matchText)))
- {
- this.uri = new Uri(url);
- this.RequireControlModifierForClick = false;
- }
-
- protected override Uri GetUriFromMatch(Match match)
- {
- return uri;
- }
- }
-
- static void AddUpdateCheckButton(StackPanel stackPanel, DecompilerTextView textView)
- {
- Button button = ThemeManager.Current.CreateButton();
- button.Content = Resources.CheckUpdates;
- button.Cursor = Cursors.Arrow;
- stackPanel.Children.Add(button);
-
- button.Click += async delegate {
- button.Content = Resources.Checking;
- button.IsEnabled = false;
-
- try
- {
- AvailableVersionInfo vInfo = await UpdateService.GetLatestVersionAsync();
- stackPanel.Children.Clear();
- ShowAvailableVersion(vInfo, stackPanel);
- }
- catch (Exception ex)
- {
- AvalonEditTextOutput exceptionOutput = new AvalonEditTextOutput();
- exceptionOutput.WriteLine(ex.ToString());
- textView.ShowText(exceptionOutput);
- }
- };
- }
-
- static void ShowAvailableVersion(AvailableVersionInfo availableVersion, StackPanel stackPanel)
- {
- if (AppUpdateService.CurrentVersion == availableVersion.Version)
- {
- stackPanel.Children.Add(
- new Image {
- Width = 16, Height = 16,
-#if CROSS_PLATFORM
- Source = Images.LoadImage(Images.OK),
-#else
- Source = Images.OK,
-#endif
- Margin = new Thickness(4, 0, 4, 0)
- });
- stackPanel.Children.Add(
- new TextBlock {
- Text = Resources.UsingLatestRelease,
- VerticalAlignment = VerticalAlignment.Bottom
- });
- }
- else if (AppUpdateService.CurrentVersion < availableVersion.Version)
- {
- stackPanel.Children.Add(
- new TextBlock {
- Text = string.Format(Resources.VersionAvailable, availableVersion.Version),
- Margin = new Thickness(0, 0, 8, 0),
- VerticalAlignment = VerticalAlignment.Bottom
- });
- if (availableVersion.DownloadUrl != null)
- {
- Button button = ThemeManager.Current.CreateButton();
- button.Content = Resources.Download;
- button.Cursor = Cursors.Arrow;
- button.Click += delegate {
- GlobalUtils.OpenLink(availableVersion.DownloadUrl);
- };
- stackPanel.Children.Add(button);
- }
- }
- else
- {
- stackPanel.Children.Add(new TextBlock { Text = Resources.UsingNightlyBuildNewerThanLatestRelease });
- }
- }
- }
-
- ///
- /// Interface that allows plugins to extend the about page.
- ///
- public interface IAboutPageAddition
- {
- void Write(ISmartTextOutput textOutput);
- }
-}
diff --git a/ILSpy/Analyzers/AnalyzeCommand.cs b/ILSpy/Analyzers/AnalyzeCommand.cs
deleted file mode 100644
index ddd5d9219..000000000
--- a/ILSpy/Analyzers/AnalyzeCommand.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Linq;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-
-using TomsToolbox.Composition;
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- [ExportContextMenuEntry(Header = nameof(Resources.Analyze), Icon = "Images/Search", Category = nameof(Resources.Analyze), InputGestureText = "Ctrl+R", Order = 100)]
- [Shared]
- internal sealed class AnalyzeContextMenuCommand(AnalyzerTreeViewModel analyzerTreeView) : IContextMenuEntry
- {
- public bool IsVisible(TextViewContext context)
- {
- if (context.TreeView is AnalyzerTreeView && context.SelectedTreeNodes != null && context.SelectedTreeNodes.All(n => n.Parent.IsRoot))
- return false;
- if (context.SelectedTreeNodes == null)
- return context.Reference != null && IsValidReference(context.Reference.Reference);
- return context.SelectedTreeNodes.All(n => n is IMemberTreeNode);
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- if (context.SelectedTreeNodes == null)
- {
- return context.Reference is { Reference: IEntity };
- }
- return context.SelectedTreeNodes
- .OfType()
- .All(node => IsValidReference(node.Member));
- }
-
- static bool IsValidReference(object reference)
- {
- return reference is IEntity and not IField { IsConst: true };
- }
-
- public void Execute(TextViewContext context)
- {
- if (context.SelectedTreeNodes != null)
- {
- foreach (var node in context.SelectedTreeNodes.OfType().ToArray())
- {
- analyzerTreeView.Analyze(node.Member);
- }
- }
- else if (context.Reference is { Reference: IEntity entity })
- {
- analyzerTreeView.Analyze(entity);
- }
- }
- }
-
- [Export]
- [Shared]
- public sealed class AnalyzeCommand(AssemblyTreeModel assemblyTreeModel, AnalyzerTreeViewModel analyzerTreeViewModel) : SimpleCommand
- {
- public override bool CanExecute(object parameter)
- {
- return assemblyTreeModel.SelectedNodes.All(n => n is IMemberTreeNode);
- }
-
- public override void Execute(object parameter)
- {
- foreach (var node in assemblyTreeModel.SelectedNodes.OfType())
- {
- analyzerTreeViewModel.Analyze(node.Member);
- }
- }
- }
-}
diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
deleted file mode 100644
index c86dc1e80..000000000
--- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Windows;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.TreeView;
-using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- ///
- /// Base class for entity nodes.
- ///
- public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode
- {
- public abstract IEntity? Member { get; }
-
- public IEntity? SourceMember { get; protected set; }
-
- public override void ActivateItem(IPlatformRoutedEventArgs e)
- {
- e.Handled = true;
- if (this.Member == null || this.Member.MetadataToken.IsNil)
- {
- MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy");
- return;
- }
-
- var module = this.Member.ParentModule?.MetadataFile;
-
- Debug.Assert(module != null);
-
- MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(module, this.Member.MetadataToken), this.SourceMember));
- }
-
- public override object? ToolTip => Member?.ParentModule?.MetadataFile?.FileName;
-
- public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies)
- {
- if (Member == null)
- {
- return true;
- }
- foreach (LoadedAssembly asm in removedAssemblies)
- {
- if (this.Member.ParentModule!.MetadataFile == asm.GetMetadataFileOrNull())
- return false; // remove this node
- }
- this.Children.RemoveAll(
- delegate (SharpTreeNode n) {
- return n is not AnalyzerTreeNode an || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
- });
- return true;
- }
- }
-}
diff --git a/ILSpy/Analyzers/AnalyzerRootNode.cs b/ILSpy/Analyzers/AnalyzerRootNode.cs
deleted file mode 100644
index 3303e5c03..000000000
--- a/ILSpy/Analyzers/AnalyzerRootNode.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2024 Tom Englert for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Linq;
-
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.TreeView;
-
-namespace ICSharpCode.ILSpy.Analyzers;
-
-public sealed class AnalyzerRootNode : AnalyzerTreeNode
-{
- public AnalyzerRootNode()
- {
- MessageBus.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e);
- }
-
- void CurrentAssemblyList_Changed(object sender, NotifyCollectionChangedEventArgs e)
- {
- if (e.Action == NotifyCollectionChangedAction.Reset)
- {
- this.Children.Clear();
- }
- else
- {
- var removedAssemblies = e.OldItems?.Cast().ToArray() ?? [];
- var addedAssemblies = e.NewItems?.Cast().ToArray() ?? [];
-
- HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
- }
- }
-
- public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies)
- {
- this.Children.RemoveAll(
- delegate (SharpTreeNode n) {
- AnalyzerTreeNode an = n as AnalyzerTreeNode;
- return an == null || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
- });
- return true;
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
deleted file mode 100644
index 9af81a856..000000000
--- a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.Analyzers.TreeNodes;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.Analyzers;
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- class AnalyzerSearchTreeNode : AnalyzerTreeNode
- {
- private readonly ThreadingSupport threading = new ThreadingSupport();
- readonly ISymbol symbol;
- readonly IAnalyzer analyzer;
- readonly string analyzerHeader;
-
- public AnalyzerSearchTreeNode(ISymbol symbol, IAnalyzer analyzer, string analyzerHeader)
- {
- this.symbol = symbol;
- this.analyzer = analyzer ?? throw new ArgumentNullException(nameof(analyzer));
- this.LazyLoading = true;
- this.analyzerHeader = analyzerHeader;
- }
-
- public override object Text => analyzerHeader
- + (Children.Count > 0 && !threading.IsRunning ? " (" + Children.Count + " in " + threading.EllapsedMilliseconds + "ms)" : "");
-
- public override object Icon => Images.Search;
-
- protected override void LoadChildren()
- {
- threading.LoadChildren(this, FetchChildren);
- }
-
- protected IEnumerable FetchChildren(CancellationToken ct)
- {
- if (symbol is IEntity)
- {
- var context = new AnalyzerContext {
- CancellationToken = ct,
- Language = Language,
- AssemblyList = AssemblyList
- };
- var results = analyzer.Analyze(symbol, context).Select(SymbolTreeNodeFactory);
- if (context.SortResults)
- {
- results = results.OrderBy(tn => tn.Text?.ToString(), NaturalStringComparer.Instance);
- }
- return results;
- }
- else
- {
- throw new NotSupportedException("Currently symbols that are not entities are not supported!");
- }
- }
-
- AnalyzerTreeNode SymbolTreeNodeFactory(ISymbol resultSymbol)
- {
- if (resultSymbol == null)
- {
- throw new ArgumentNullException(nameof(resultSymbol));
- }
-
- switch (resultSymbol)
- {
- case IModule module:
- return new AnalyzedModuleTreeNode(module, (IEntity)this.symbol);
- case ITypeDefinition td:
- return new AnalyzedTypeTreeNode(td, (IEntity)this.symbol);
- case IField fd:
- return new AnalyzedFieldTreeNode(fd, (IEntity)this.symbol);
- case IMethod md:
- return new AnalyzedMethodTreeNode(md, (IEntity)this.symbol);
- case IProperty pd:
- return new AnalyzedPropertyTreeNode(pd, (IEntity)this.symbol);
- case IEvent ed:
- return new AnalyzedEventTreeNode(ed, (IEntity)this.symbol);
- default:
- throw new ArgumentOutOfRangeException(nameof(resultSymbol), $"Symbol {resultSymbol.GetType().FullName} is not supported.");
- }
- }
-
- protected override void OnIsVisibleChanged()
- {
- base.OnIsVisibleChanged();
- if (!this.IsVisible && threading.IsRunning)
- {
- this.LazyLoading = true;
- threading.Cancel();
- this.Children.Clear();
- RaisePropertyChanged(nameof(Text));
- }
- }
-
- public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies)
- {
- // only cancel a running analysis if user has manually added/removed assemblies
- bool manualAdd = false;
- foreach (var asm in addedAssemblies)
- {
- if (!asm.IsAutoLoaded)
- manualAdd = true;
- }
- if (removedAssemblies.Count > 0 || manualAdd)
- {
- this.LazyLoading = true;
- threading.Cancel();
- this.Children.Clear();
- RaisePropertyChanged(nameof(Text));
- }
- return true;
- }
- }
-}
diff --git a/ILSpy/Analyzers/AnalyzerTreeNode.cs b/ILSpy/Analyzers/AnalyzerTreeNode.cs
deleted file mode 100644
index 378b4701d..000000000
--- a/ILSpy/Analyzers/AnalyzerTreeNode.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Collections.Generic;
-using System.Linq;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.Analyzers;
-using ICSharpCode.ILSpyX.TreeView;
-
-using TomsToolbox.Composition;
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- public abstract class AnalyzerTreeNode : SharpTreeNode
- {
- protected static Language Language => App.ExportProvider.GetExportedValue().Language;
-
- protected static AssemblyList AssemblyList => App.ExportProvider.GetExportedValue();
-
- public override bool CanDelete()
- {
- return Parent is { IsRoot: true };
- }
-
- public override void DeleteCore()
- {
- Parent.Children.Remove(this);
- }
-
- public override void Delete()
- {
- DeleteCore();
- }
-
- public static ICollection> Analyzers => App.ExportProvider
- .GetExports("Analyzer")
- .OrderBy(item => item.Metadata?.Order)
- .ToArray();
-
- ///
- /// Handles changes to the assembly list.
- ///
- public abstract bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies);
- }
-}
diff --git a/ILSpy/Analyzers/AnalyzerTreeView.xaml b/ILSpy/Analyzers/AnalyzerTreeView.xaml
deleted file mode 100644
index a469779de..000000000
--- a/ILSpy/Analyzers/AnalyzerTreeView.xaml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ILSpy/Analyzers/AnalyzerTreeView.xaml.cs b/ILSpy/Analyzers/AnalyzerTreeView.xaml.cs
deleted file mode 100644
index 98d4e826d..000000000
--- a/ILSpy/Analyzers/AnalyzerTreeView.xaml.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Windows.Controls;
-
-using ICSharpCode.ILSpyX.TreeView;
-
-using TomsToolbox.Wpf.Composition.AttributedModel;
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- ///
- /// Interaction logic for AnalyzerTreeView.xaml
- ///
- [DataTemplate(typeof(AnalyzerTreeViewModel))]
- [NonShared]
- [Export]
- public partial class AnalyzerTreeView
- {
- public AnalyzerTreeView()
- {
- InitializeComponent();
- ContextMenuProvider.Add(this);
- }
-
- private void AnalyzerTreeView_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (SelectedItem is SharpTreeNode sharpTreeNode)
- {
- FocusNode(sharpTreeNode);
- }
- }
- }
-}
diff --git a/ILSpy/Analyzers/AnalyzerTreeViewModel.cs b/ILSpy/Analyzers/AnalyzerTreeViewModel.cs
deleted file mode 100644
index 5e8a975c2..000000000
--- a/ILSpy/Analyzers/AnalyzerTreeViewModel.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2024 Tom Englert for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Composition;
-using System.Linq;
-using System.Windows;
-using System.Windows.Input;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.Analyzers.TreeNodes;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpyX.TreeView;
-
-using TomsToolbox.Wpf;
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- [ExportToolPane]
- [Shared]
- [Export]
- public class AnalyzerTreeViewModel : ToolPaneModel
- {
- public const string PaneContentId = "analyzerPane";
-
- public AnalyzerTreeViewModel(AssemblyTreeModel assemblyTreeModel)
- {
- ContentId = PaneContentId;
- Title = Properties.Resources.Analyze;
- ShortcutKey = new(Key.R, ModifierKeys.Control);
- AssociatedCommand = new AnalyzeCommand(assemblyTreeModel, this);
- }
-
- public AnalyzerRootNode Root { get; } = new();
-
- public ICommand AnalyzeCommand => new DelegateCommand(AnalyzeSelected);
-
- private SharpTreeNode[] selectedItems = [];
-
- public SharpTreeNode[] SelectedItems {
- get => selectedItems ?? [];
- set {
- if (SelectedItems.SequenceEqual(value))
- return;
-
- selectedItems = value;
- OnPropertyChanged();
- }
- }
-
- private void AnalyzeSelected()
- {
- foreach (var node in SelectedItems.OfType())
- {
- Analyze(node.Member);
- }
- }
-
- void AddOrSelect(AnalyzerTreeNode node)
- {
- Show();
-
- AnalyzerTreeNode target = default;
-
- if (node is AnalyzerEntityTreeNode { Member: { } member })
- {
- target = this.Root.Children.OfType().FirstOrDefault(item => item.Member == member);
- }
-
- if (target == null)
- {
- this.Root.Children.Add(node);
- target = node;
- }
-
- target.IsExpanded = true;
- this.SelectedItems = [target];
- }
-
- public void Analyze(IEntity entity)
- {
- if (entity == null)
- {
- throw new ArgumentNullException(nameof(entity));
- }
-
- if (entity.MetadataToken.IsNil)
- {
- MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy");
- return;
- }
-
- switch (entity)
- {
- case ITypeDefinition td:
- AddOrSelect(new AnalyzedTypeTreeNode(td, null));
- break;
- case IField fd:
- if (!fd.IsConst)
- AddOrSelect(new AnalyzedFieldTreeNode(fd, null));
- break;
- case IMethod md:
- AddOrSelect(new AnalyzedMethodTreeNode(md, null));
- break;
- case IProperty pd:
- AddOrSelect(new AnalyzedPropertyTreeNode(pd, null));
- break;
- case IEvent ed:
- AddOrSelect(new AnalyzedEventTreeNode(ed, null));
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(entity), $@"Entity {entity.GetType().FullName} is not supported.");
- }
- }
- }
-}
-
diff --git a/ILSpy/Analyzers/CopyAnalysisResultsContextMenuEntry.cs b/ILSpy/Analyzers/CopyAnalysisResultsContextMenuEntry.cs
deleted file mode 100644
index 2e9152722..000000000
--- a/ILSpy/Analyzers/CopyAnalysisResultsContextMenuEntry.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2022 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Linq;
-using System.Text;
-using System.Windows;
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- [ExportContextMenuEntry(Header = "Copy results", Category = "Analyze", Order = 200)]
- [Shared]
- internal sealed class CopyAnalysisResultsContextMenuEntry : IContextMenuEntry
- {
- public bool IsVisible(TextViewContext context)
- {
- if (context.TreeView is AnalyzerTreeView && context.SelectedTreeNodes != null && context.SelectedTreeNodes.All(n => n is AnalyzerSearchTreeNode))
- return true;
- return false;
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- return true;
- }
-
- public void Execute(TextViewContext context)
- {
- StringBuilder sb = new StringBuilder();
- if (context.SelectedTreeNodes != null)
- {
- foreach (var node in context.SelectedTreeNodes)
- {
- foreach (var item in node.Children)
- {
- sb.AppendLine(item.Text.ToString());
- }
- }
- }
- Clipboard.SetText(sb.ToString());
- }
- }
-}
diff --git a/ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs b/ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs
deleted file mode 100644
index 6969c605e..000000000
--- a/ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2013 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Linq;
-
-namespace ICSharpCode.ILSpy.Analyzers
-{
- [ExportContextMenuEntry(Header = "Remove", Icon = "images/Delete", Category = "Analyze", Order = 200)]
- [Shared]
- internal sealed class RemoveAnalyzeContextMenuEntry : IContextMenuEntry
- {
- public bool IsVisible(TextViewContext context)
- {
- if (context.TreeView is AnalyzerTreeView && context.SelectedTreeNodes != null && context.SelectedTreeNodes.All(n => n.Parent.IsRoot))
- return true;
- return false;
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- return true;
- }
-
- public void Execute(TextViewContext context)
- {
- if (context.SelectedTreeNodes != null)
- {
- foreach (var node in context.SelectedTreeNodes)
- {
- node.Parent.Children.Remove(node);
- }
- }
- }
- }
-}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs
deleted file mode 100644
index 08b44dabe..000000000
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedAccessorTreeNode.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using ICSharpCode.Decompiler.TypeSystem;
-
-namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
-{
- class AnalyzedAccessorTreeNode : AnalyzedMethodTreeNode
- {
- readonly string name;
-
- public AnalyzedAccessorTreeNode(IMethod analyzedMethod, IEntity source, string name)
- : base(analyzedMethod, source)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- throw new System.ArgumentException("name must be a non-empty string", nameof(name));
- }
-
- this.name = name;
- }
-
- public override object Text => name;
- }
-}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
deleted file mode 100644
index 9df55a061..000000000
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-
-using ICSharpCode.Decompiler.Output;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.TreeNodes;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
-{
- internal sealed class AnalyzedEventTreeNode : AnalyzerEntityTreeNode
- {
- readonly IEvent analyzedEvent;
- readonly string prefix;
-
- public AnalyzedEventTreeNode(IEvent analyzedEvent, IEntity? source, string prefix = "")
- {
- this.analyzedEvent = analyzedEvent ?? throw new ArgumentNullException(nameof(analyzedEvent));
- this.prefix = prefix;
- this.LazyLoading = true;
- this.SourceMember = source;
- }
-
- public override IEntity Member => analyzedEvent;
-
- public override object Icon => EventTreeNode.GetIcon(analyzedEvent);
-
- // TODO: This way of formatting is not suitable for events which explicitly implement interfaces.
- public override object Text => prefix + Language.EntityToString(analyzedEvent, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
-
- protected override void LoadChildren()
- {
- if (analyzedEvent.CanAdd)
- this.Children.Add(new AnalyzedAccessorTreeNode(analyzedEvent.AddAccessor, this.SourceMember, "add"));
- if (analyzedEvent.CanRemove)
- this.Children.Add(new AnalyzedAccessorTreeNode(analyzedEvent.RemoveAccessor, this.SourceMember, "remove"));
- if (TryFindBackingField(analyzedEvent, out var backingField))
- this.Children.Add(new AnalyzedFieldTreeNode(backingField, this.SourceMember));
-
- foreach (var lazy in Analyzers)
- {
- var analyzer = lazy.Value;
- Debug.Assert(analyzer != null);
- if (analyzer.Show(analyzedEvent))
- {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedEvent, analyzer, lazy.Metadata?.Header));
- }
- }
- }
-
- bool TryFindBackingField(IEvent analyzedEvent, [NotNullWhen(true)] out IField? backingField)
- {
- backingField = null;
- foreach (var field in analyzedEvent.DeclaringTypeDefinition?.GetFields(options: GetMemberOptions.IgnoreInheritedMembers) ?? [])
- {
- if (field.Name == analyzedEvent.Name && field.Accessibility == Decompiler.TypeSystem.Accessibility.Private)
- {
- backingField = field;
- return true;
- }
- }
- return false;
- }
- }
-}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
deleted file mode 100644
index 64a508c57..000000000
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Diagnostics;
-
-using ICSharpCode.Decompiler.Output;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.TreeNodes;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
-{
- class AnalyzedFieldTreeNode : AnalyzerEntityTreeNode
- {
- readonly IField analyzedField;
-
- public AnalyzedFieldTreeNode(IField analyzedField, IEntity? source)
- {
- this.analyzedField = analyzedField ?? throw new ArgumentNullException(nameof(analyzedField));
- this.SourceMember = source;
- this.LazyLoading = true;
- }
-
- public override object Icon => FieldTreeNode.GetIcon(analyzedField);
-
- public override object Text => Language.EntityToString(analyzedField, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
-
- protected override void LoadChildren()
- {
- foreach (var lazy in Analyzers)
- {
- var analyzer = lazy.Value;
- Debug.Assert(analyzer != null);
- if (analyzer.Show(analyzedField))
- {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedField, analyzer, lazy.Metadata?.Header));
- }
- }
- }
-
- public override IEntity Member => analyzedField;
- }
-}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
deleted file mode 100644
index 2ce76fe51..000000000
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Diagnostics;
-
-using ICSharpCode.Decompiler.Output;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.TreeNodes;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
-{
- internal class AnalyzedMethodTreeNode : AnalyzerEntityTreeNode
- {
- readonly IMethod analyzedMethod;
- readonly string prefix;
-
- public AnalyzedMethodTreeNode(IMethod analyzedMethod, IEntity? source, string prefix = "")
- {
- this.analyzedMethod = analyzedMethod ?? throw new ArgumentNullException(nameof(analyzedMethod));
- this.SourceMember = source;
- this.prefix = prefix;
- this.LazyLoading = true;
- }
-
- public override object Icon => MethodTreeNode.GetIcon(analyzedMethod);
-
- public override object Text => prefix + Language.EntityToString(analyzedMethod, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
-
- protected override void LoadChildren()
- {
- foreach (var lazy in Analyzers)
- {
- var analyzer = lazy.Value;
- Debug.Assert(analyzer != null);
- if (analyzer.Show(analyzedMethod))
- {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedMethod, analyzer, lazy.Metadata!.Header));
- }
- }
- }
-
- public override IEntity Member => analyzedMethod;
- }
-}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs
deleted file mode 100644
index 7695b625f..000000000
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Windows;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.TreeView;
-using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
-{
- internal class AnalyzedModuleTreeNode : AnalyzerEntityTreeNode
- {
- readonly IModule analyzedModule;
-
- public AnalyzedModuleTreeNode(IModule analyzedModule, IEntity? source)
- {
- this.analyzedModule = analyzedModule ?? throw new ArgumentNullException(nameof(analyzedModule));
- this.SourceMember = source;
- this.LazyLoading = true;
- }
-
- public override object Icon => Images.Assembly;
-
- public override object Text => analyzedModule.AssemblyName;
-
- public override object? ToolTip => analyzedModule.MetadataFile?.FileName;
-
- protected override void LoadChildren()
- {
- foreach (var lazy in Analyzers)
- {
- var analyzer = lazy.Value;
- Debug.Assert(analyzer != null);
- if (analyzer.Show(analyzedModule))
- {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedModule, analyzer, lazy.Metadata!.Header));
- }
- }
- }
-
- public override void ActivateItem(IPlatformRoutedEventArgs e)
- {
- e.Handled = true;
- if (analyzedModule.MetadataFile == null)
- {
- MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy");
- return;
- }
- MessageBus.Send(this, new NavigateToReferenceEventArgs(analyzedModule.MetadataFile));
- }
-
- public override IEntity? Member => null;
-
- public override bool HandleAssemblyListChanged(ICollection removedAssemblies, ICollection addedAssemblies)
- {
- if (analyzedModule == null)
- {
- return true;
- }
- foreach (LoadedAssembly asm in removedAssemblies)
- {
- if (this.analyzedModule.MetadataFile == asm.GetMetadataFileOrNull())
- return false; // remove this node
- }
- this.Children.RemoveAll(
- delegate (SharpTreeNode n) {
- return n is not AnalyzerTreeNode an || !an.HandleAssemblyListChanged(removedAssemblies, addedAssemblies);
- });
- return true;
- }
- }
-}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
deleted file mode 100644
index d6cb1df5e..000000000
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Diagnostics;
-
-using ICSharpCode.Decompiler.Output;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.TreeNodes;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
-{
- sealed class AnalyzedPropertyTreeNode : AnalyzerEntityTreeNode
- {
- readonly IProperty analyzedProperty;
- readonly string prefix;
-
- public AnalyzedPropertyTreeNode(IProperty analyzedProperty, IEntity? source, string prefix = "")
- {
- this.analyzedProperty = analyzedProperty ?? throw new ArgumentNullException(nameof(analyzedProperty));
- this.prefix = prefix;
- this.LazyLoading = true;
- this.SourceMember = source;
- }
-
- public override object Icon => PropertyTreeNode.GetIcon(analyzedProperty);
-
- // TODO: This way of formatting is not suitable for properties which explicitly implement interfaces.
- public override object Text => prefix + Language.EntityToString(analyzedProperty, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
-
- protected override void LoadChildren()
- {
- if (analyzedProperty.CanGet)
- this.Children.Add(new AnalyzedAccessorTreeNode(analyzedProperty.Getter, this.SourceMember, "get"));
- if (analyzedProperty.CanSet)
- this.Children.Add(new AnalyzedAccessorTreeNode(analyzedProperty.Setter, this.SourceMember, "set"));
-
- foreach (var lazy in Analyzers)
- {
- var analyzer = lazy.Value;
- Debug.Assert(analyzer != null);
- if (analyzer.Show(analyzedProperty))
- {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedProperty, analyzer, lazy.Metadata!.Header));
- }
- }
- }
-
- public override IEntity Member => analyzedProperty;
- }
-}
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
deleted file mode 100644
index 67f37d6f9..000000000
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Diagnostics;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.TreeNodes;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
-{
- internal class AnalyzedTypeTreeNode : AnalyzerEntityTreeNode
- {
- readonly ITypeDefinition analyzedType;
-
- public AnalyzedTypeTreeNode(ITypeDefinition analyzedType, IEntity? source)
- {
- this.analyzedType = analyzedType ?? throw new ArgumentNullException(nameof(analyzedType));
- this.SourceMember = source;
- this.LazyLoading = true;
- }
-
- public override object Icon => TypeTreeNode.GetIcon(analyzedType);
-
- public override object Text => Language.TypeToString(analyzedType);
-
- protected override void LoadChildren()
- {
- foreach (var lazy in Analyzers)
- {
- var analyzer = lazy.Value;
- Debug.Assert(analyzer != null);
- if (analyzer.Show(analyzedType))
- {
- this.Children.Add(new AnalyzerSearchTreeNode(analyzedType, analyzer, lazy.Metadata!.Header));
- }
- }
- }
-
- public override IEntity Member => analyzedType;
- }
-}
diff --git a/ILSpy/App.xaml b/ILSpy/App.xaml
deleted file mode 100644
index 1e24beebf..000000000
--- a/ILSpy/App.xaml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs
deleted file mode 100644
index 66f81e7a4..000000000
--- a/ILSpy/App.xaml.cs
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.Loader;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Threading;
-
-using ICSharpCode.ILSpy.AppEnv;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpyX.Analyzers;
-
-using Medo.Application;
-
-using TomsToolbox.Wpf.Styles;
-using ICSharpCode.ILSpyX.TreeView;
-
-using TomsToolbox.Composition;
-using TomsToolbox.Wpf.Composition;
-using ICSharpCode.ILSpy.Themes;
-using System.Globalization;
-using System.Threading;
-
-using Microsoft.Extensions.DependencyInjection;
-
-using TomsToolbox.Composition.MicrosoftExtensions;
-using TomsToolbox.Essentials;
-
-namespace ICSharpCode.ILSpy
-{
- ///
- /// Interaction logic for App.xaml
- ///
- public partial class App : Application
- {
- internal static CommandLineArguments CommandLineArguments;
- internal static readonly IList StartupExceptions = new List();
-
- public static IExportProvider ExportProvider { get; private set; }
-
- internal record ExceptionData(Exception Exception)
- {
- public string PluginName { get; init; }
- }
-
- public App()
- {
- var cmdArgs = Environment.GetCommandLineArgs().Skip(1);
- CommandLineArguments = CommandLineArguments.Create(cmdArgs);
-
- // This is only a temporary, read only handle to the settings service to access the AllowMultipleInstances setting before DI is initialized.
- // At runtime, you must use the service via DI!
- var settingsService = new SettingsService();
-
- bool forceSingleInstance = (CommandLineArguments.SingleInstance ?? true)
- && !settingsService.MiscSettings.AllowMultipleInstances;
- if (forceSingleInstance)
- {
- SingleInstance.Attach(); // will auto-exit for second instance
- SingleInstance.NewInstanceDetected += SingleInstance_NewInstanceDetected;
- }
-
- InitializeComponent();
-
- if (!InitializeDependencyInjection(settingsService))
- {
- // There is something completely wrong with DI, probably some service registration is missing => nothing we can do to recover, so stop and shut down.
- Exit += (_, _) => MessageBox.Show(StartupExceptions.FormatExceptions(), "Sorry we crashed!", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
- Shutdown(1);
- return;
- }
-
- if (!Debugger.IsAttached)
- {
- AppDomain.CurrentDomain.UnhandledException += ShowErrorBox;
- Dispatcher.CurrentDispatcher.UnhandledException += Dispatcher_UnhandledException;
- }
-
- TaskScheduler.UnobservedTaskException += DotNet40_UnobservedTaskException;
-
- SharpTreeNode.SetImagesProvider(new WpfWindowsTreeNodeImagesProvider());
-
- Resources.RegisterDefaultStyles();
-
- // Register the export provider so that it can be accessed from WPF/XAML components.
- ExportProviderLocator.Register(ExportProvider);
- // Add data templates registered via MEF.
- Resources.MergedDictionaries.Add(DataTemplateManager.CreateDynamicDataTemplates(ExportProvider));
-
- var sessionSettings = settingsService.SessionSettings;
- ThemeManager.Current.Theme = sessionSettings.Theme;
- if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture))
- {
- Thread.CurrentThread.CurrentUICulture = CultureInfo.DefaultThreadCurrentUICulture = new(sessionSettings.CurrentCulture);
- }
-
- ILSpyTraceListener.Install();
-
- if (CommandLineArguments.ArgumentsParser.IsShowingInformation)
- {
- MessageBox.Show(CommandLineArguments.ArgumentsParser.GetHelpText(), "ILSpy Command Line Arguments");
- }
-
- if (CommandLineArguments.ArgumentsParser.RemainingArguments.Any())
- {
- string unknownArguments = string.Join(", ", CommandLineArguments.ArgumentsParser.RemainingArguments);
- MessageBox.Show(unknownArguments, "ILSpy Unknown Command Line Arguments Passed");
- }
-
- settingsService.AssemblyListManager.CreateDefaultAssemblyLists();
- }
-
- public new static App Current => (App)Application.Current;
-
- public new MainWindow MainWindow {
- get => (MainWindow)base.MainWindow;
- private set => base.MainWindow = value;
- }
-
- private static void SingleInstance_NewInstanceDetected(object sender, NewInstanceEventArgs e) => ExportProvider.GetExportedValue().HandleSingleInstanceCommandLineArguments(e.Args).HandleExceptions();
-
- static Assembly ResolvePluginDependencies(AssemblyLoadContext context, AssemblyName assemblyName)
- {
- var rootPath = Path.GetDirectoryName(typeof(App).Assembly.Location);
- var assemblyFileName = Path.Combine(rootPath, assemblyName.Name + ".dll");
- if (!File.Exists(assemblyFileName))
- return null;
- return context.LoadFromAssemblyPath(assemblyFileName);
- }
-
- private bool InitializeDependencyInjection(SettingsService settingsService)
- {
- // Add custom logic for resolution of dependencies.
- // This necessary because the AssemblyLoadContext.LoadFromAssemblyPath and related methods,
- // do not automatically load dependencies.
- AssemblyLoadContext.Default.Resolving += ResolvePluginDependencies;
- try
- {
- var services = new ServiceCollection();
-
- var pluginDir = Path.GetDirectoryName(typeof(App).Module.FullyQualifiedName);
- if (pluginDir != null)
- {
- foreach (var plugin in Directory.GetFiles(pluginDir, "*.Plugin.dll"))
- {
- var name = Path.GetFileNameWithoutExtension(plugin);
- try
- {
- var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(plugin);
- services.BindExports(assembly);
- }
- catch (Exception ex)
- {
- // Cannot show MessageBox here, because WPF would crash with a XamlParseException
- // Remember and show exceptions in text output, once MainWindow is properly initialized
- StartupExceptions.Add(new(ex) { PluginName = name });
- }
- }
- }
-
- // Add the built-in parts: First, from ILSpyX
- services.BindExports(typeof(IAnalyzer).Assembly);
- // Then from ILSpy itself
- services.BindExports(Assembly.GetExecutingAssembly());
- // Add the settings service
- services.AddSingleton(settingsService);
- // Add the export provider
- services.AddSingleton(_ => ExportProvider);
- // Add the docking manager
- services.AddSingleton(serviceProvider => serviceProvider.GetService().DockManager);
- services.AddTransient(serviceProvider => serviceProvider.GetService().AssemblyList);
-
- var serviceProvider = services.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true });
-
- ExportProvider = new ExportProviderAdapter(serviceProvider);
-
- Exit += (_, _) => serviceProvider.Dispose();
-
- return true;
- }
- catch (Exception ex)
- {
- if (ex is AggregateException aggregate)
- StartupExceptions.AddRange(aggregate.InnerExceptions.Select(item => new ExceptionData(ex)));
- else
- StartupExceptions.Add(new(ex));
-
- return false;
- }
- }
-
- protected override void OnStartup(StartupEventArgs e)
- {
- base.OnStartup(e);
-
- MainWindow = ExportProvider.GetExportedValue();
- MainWindow.Show();
- }
-
- void DotNet40_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
- {
- // On .NET 4.0, an unobserved exception in a task terminates the process unless we mark it as observed
- e.SetObserved();
- }
-
- #region Exception Handling
- static void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
- {
- UnhandledException(e.Exception);
- e.Handled = true;
- }
-
- static void ShowErrorBox(object sender, UnhandledExceptionEventArgs e)
- {
- Exception ex = e.ExceptionObject as Exception;
- if (ex != null)
- {
- UnhandledException(ex);
- }
- }
-
- [ThreadStatic]
- static bool showingError;
-
- internal static void UnhandledException(Exception exception)
- {
- Debug.WriteLine(exception.ToString());
- for (Exception ex = exception; ex != null; ex = ex.InnerException)
- {
- ReflectionTypeLoadException rtle = ex as ReflectionTypeLoadException;
- if (rtle != null && rtle.LoaderExceptions.Length > 0)
- {
- exception = rtle.LoaderExceptions[0];
- Debug.WriteLine(exception.ToString());
- break;
- }
- }
- if (showingError)
- {
- // Ignore re-entrant calls
- // We run the risk of opening an infinite number of exception dialogs.
- return;
- }
- showingError = true;
- try
- {
- MessageBox.Show(exception.ToString(), "Sorry, we crashed");
- }
- finally
- {
- showingError = false;
- }
- }
- #endregion
- }
-}
\ No newline at end of file
diff --git a/ILSpy/AppEnv/AppEnvironment.cs b/ILSpy/AppEnv/AppEnvironment.cs
deleted file mode 100644
index 2916f855b..000000000
--- a/ILSpy/AppEnv/AppEnvironment.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace ICSharpCode.ILSpy.AppEnv
-{
- public static class AppEnvironment
- {
- public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
- }
-}
diff --git a/ILSpy/AppEnv/CommandLineArguments.cs b/ILSpy/AppEnv/CommandLineArguments.cs
deleted file mode 100644
index 2f54879e7..000000000
--- a/ILSpy/AppEnv/CommandLineArguments.cs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using McMaster.Extensions.CommandLineUtils;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace ICSharpCode.ILSpy.AppEnv
-{
- public sealed class CommandLineArguments
- {
- // see /doc/Command Line.txt for details
- public List AssembliesToLoad = new List();
- public bool? SingleInstance;
- public string NavigateTo;
- public string Search;
- public string Language;
- public bool NoActivate;
- public string ConfigFile;
-
- public CommandLineApplication ArgumentsParser { get; }
-
- private CommandLineArguments(CommandLineApplication app)
- {
- ArgumentsParser = app;
- }
-
- public static CommandLineArguments Create(IEnumerable arguments)
- {
- var app = new CommandLineApplication() {
- // https://natemcmaster.github.io/CommandLineUtils/docs/response-file-parsing.html?tabs=using-attributes
- ResponseFileHandling = ResponseFileHandling.ParseArgsAsLineSeparated,
-
- // Note: options are case-sensitive (!), and, default behavior would be UnrecognizedArgumentHandling.Throw on Parse()
- UnrecognizedArgumentHandling = UnrecognizedArgumentHandling.CollectAndContinue
- };
-
- app.HelpOption();
- var instance = new CommandLineArguments(app);
-
- try
- {
- var oForceNewInstance = app.Option("--newinstance",
- "Start a new instance of ILSpy even if the user configuration is set to single-instance",
- CommandOptionType.NoValue);
-
- var oNavigateTo = app.Option("-n|--navigateto ",
- "Navigates to the member specified by the given ID string.\r\nThe member is searched for only in the assemblies specified on the command line.\r\nExample: 'ILSpy ILSpy.exe --navigateto T:ICSharpCode.ILSpy.CommandLineArguments'",
- CommandOptionType.SingleValue);
- oNavigateTo.DefaultValue = null;
-
- var oSearch = app.Option("-s|--search ",
- "Search for t:TypeName, m:Member or c:Constant; use exact match (=term), 'should not contain' (-term) or 'must contain' (+term); use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/...",
- CommandOptionType.SingleValue);
- oSearch.DefaultValue = null;
-
- var oLanguage = app.Option("-l|--language ",
- "Selects the specified language.\r\nExample: 'ILSpy --language:C#' or 'ILSpy --language IL'",
- CommandOptionType.SingleValue);
- oLanguage.DefaultValue = null;
-
- var oConfig = app.Option("-c|--config ",
- "Provide a specific configuration file.\r\nExample: 'ILSpy --config myconfig.xml'",
- CommandOptionType.SingleValue);
- oConfig.DefaultValue = null;
-
- var oNoActivate = app.Option("--noactivate",
- "Do not activate the existing ILSpy instance. This option has no effect if a new ILSpy instance is being started.",
- CommandOptionType.NoValue);
-
- // https://natemcmaster.github.io/CommandLineUtils/docs/arguments.html#variable-numbers-of-arguments
- // To enable this, MultipleValues must be set to true, and the argument must be the last one specified.
- var files = app.Argument("Assemblies", "Assemblies to load", multipleValues: true);
-
- app.Parse(arguments.ToArray());
-
- if (oForceNewInstance.HasValue())
- instance.SingleInstance = false;
-
- instance.NavigateTo = oNavigateTo.ParsedValue;
- instance.Search = oSearch.ParsedValue;
- instance.Language = oLanguage.ParsedValue;
- instance.ConfigFile = oConfig.ParsedValue;
-
- if (oNoActivate.HasValue())
- instance.NoActivate = true;
-
- foreach (var assembly in files.Values)
- {
- if (!string.IsNullOrWhiteSpace(assembly))
- instance.AssembliesToLoad.Add(assembly);
- }
- }
- catch (Exception)
- {
- // Intentionally ignore exceptions if any, this is only added to always have an exception-free startup
- }
-
- return instance;
- }
- }
-}
diff --git a/ILSpy/AppEnv/CommandLineTools.cs b/ILSpy/AppEnv/CommandLineTools.cs
deleted file mode 100644
index 898f56c36..000000000
--- a/ILSpy/AppEnv/CommandLineTools.cs
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (c) 2024 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-
-namespace ICSharpCode.ILSpy.AppEnv
-{
- public class CommandLineTools
- {
- ///
- /// Decodes a command line into an array of arguments according to the CommandLineToArgvW rules.
- ///
- ///
- /// Command line parsing rules:
- /// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument.
- /// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
- /// - n backslashes not followed by a quotation mark simply produce n backslashes.
- ///
- public static string[] CommandLineToArgumentArray(string commandLine)
- {
- if (string.IsNullOrEmpty(commandLine))
- return Array.Empty();
-
- var results = new List();
- ParseArgv.ParseArgumentsIntoList(commandLine, results);
-
- return results.ToArray();
- }
-
- static readonly char[] charsNeedingQuoting = { ' ', '\t', '\n', '\v', '"' };
-
- ///
- /// Escapes a set of arguments according to the CommandLineToArgvW rules.
- ///
- ///
- /// Command line parsing rules:
- /// - 2n backslashes followed by a quotation mark produce n backslashes, and the quotation mark is considered to be the end of the argument.
- /// - (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
- /// - n backslashes not followed by a quotation mark simply produce n backslashes.
- ///
- public static string ArgumentArrayToCommandLine(params string[] arguments)
- {
- if (arguments == null)
- return null;
- StringBuilder b = new StringBuilder();
- for (int i = 0; i < arguments.Length; i++)
- {
- if (i > 0)
- b.Append(' ');
- AppendArgument(b, arguments[i]);
- }
- return b.ToString();
- }
-
- static void AppendArgument(StringBuilder b, string arg)
- {
- if (arg == null)
- {
- return;
- }
-
- if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0)
- {
- b.Append(arg);
- }
- else
- {
- b.Append('"');
- for (int j = 0; ; j++)
- {
- int backslashCount = 0;
- while (j < arg.Length && arg[j] == '\\')
- {
- backslashCount++;
- j++;
- }
- if (j == arg.Length)
- {
- b.Append('\\', backslashCount * 2);
- break;
- }
- else if (arg[j] == '"')
- {
- b.Append('\\', backslashCount * 2 + 1);
- b.Append('"');
- }
- else
- {
- b.Append('\\', backslashCount);
- b.Append(arg[j]);
- }
- }
- b.Append('"');
- }
- }
-
- public static string FullyQualifyPath(string argument)
- {
- // Fully qualify the paths before passing them to another process,
- // because that process might use a different current directory.
- if (string.IsNullOrEmpty(argument) || argument[0] == '-')
- return argument;
- try
- {
- if (argument.StartsWith("@"))
- {
- return "@" + FullyQualifyPath(argument.Substring(1));
- }
- return Path.Combine(Environment.CurrentDirectory, argument);
- }
- catch (ArgumentException)
- {
- return argument;
- }
- }
- }
-
- // Source: https://github.com/dotnet/runtime/blob/bc9fc5a774d96f95abe0ea5c90fac48b38ed2e67/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs#L574-L606
- // Minor adaptations in GetNextArgument (ValueStringBuilder replaced), otherwise kept as identical as possible
- public static class ParseArgv
- {
- /// Parses a command-line argument string into a list of arguments.
- /// The argument string.
- /// The list into which the component arguments should be stored.
- ///
- /// This follows the rules outlined in "Parsing C++ Command-Line Arguments" at
- /// https://msdn.microsoft.com/en-us/library/17w5ykft.aspx.
- ///
- public static void ParseArgumentsIntoList(string arguments, List results)
- {
- // Iterate through all of the characters in the argument string.
- for (int i = 0; i < arguments.Length; i++)
- {
- while (i < arguments.Length && (arguments[i] == ' ' || arguments[i] == '\t'))
- i++;
-
- if (i == arguments.Length)
- break;
-
- results.Add(GetNextArgument(arguments, ref i));
- }
- }
-
- private static string GetNextArgument(string arguments, ref int i)
- {
- var currentArgument = new StringBuilder();
- bool inQuotes = false;
-
- while (i < arguments.Length)
- {
- // From the current position, iterate through contiguous backslashes.
- int backslashCount = 0;
- while (i < arguments.Length && arguments[i] == '\\')
- {
- i++;
- backslashCount++;
- }
-
- if (backslashCount > 0)
- {
- if (i >= arguments.Length || arguments[i] != '"')
- {
- // Backslashes not followed by a double quote:
- // they should all be treated as literal backslashes.
- currentArgument.Append('\\', backslashCount);
- }
- else
- {
- // Backslashes followed by a double quote:
- // - Output a literal slash for each complete pair of slashes
- // - If one remains, use it to make the subsequent quote a literal.
- currentArgument.Append('\\', backslashCount / 2);
- if (backslashCount % 2 != 0)
- {
- currentArgument.Append('"');
- i++;
- }
- }
-
- continue;
- }
-
- char c = arguments[i];
-
- // If this is a double quote, track whether we're inside of quotes or not.
- // Anything within quotes will be treated as a single argument, even if
- // it contains spaces.
- if (c == '"')
- {
- if (inQuotes && i < arguments.Length - 1 && arguments[i + 1] == '"')
- {
- // Two consecutive double quotes inside an inQuotes region should result in a literal double quote
- // (the parser is left in the inQuotes region).
- // This behavior is not part of the spec of code:ParseArgumentsIntoList, but is compatible with CRT
- // and .NET Framework.
- currentArgument.Append('"');
- i++;
- }
- else
- {
- inQuotes = !inQuotes;
- }
-
- i++;
- continue;
- }
-
- // If this is a space/tab and we're not in quotes, we're done with the current
- // argument, it should be added to the results and then reset for the next one.
- if ((c == ' ' || c == '\t') && !inQuotes)
- {
- break;
- }
-
- // Nothing special; add the character to the current argument.
- currentArgument.Append(c);
- i++;
- }
-
- return currentArgument.ToString();
- }
- }
-}
diff --git a/ILSpy/AppEnv/SingleInstance.cs b/ILSpy/AppEnv/SingleInstance.cs
deleted file mode 100644
index 8fa6e2ce4..000000000
--- a/ILSpy/AppEnv/SingleInstance.cs
+++ /dev/null
@@ -1,286 +0,0 @@
-// Source: https://github.com/medo64/Medo/blob/main/src/Medo/Application/SingleInstance.cs
-
-/* Josip Medved * www.medo64.com * MIT License */
-
-//2022-12-01: Compatible with .NET 6 and 7
-//2012-11-24: Suppressing bogus CA5122 warning (http://connect.microsoft.com/VisualStudio/feedback/details/729254/bogus-ca5122-warning-about-p-invoke-declarations-should-not-be-safe-critical)
-//2010-10-07: Added IsOtherInstanceRunning method
-//2008-11-14: Reworked code to use SafeHandle
-//2008-04-11: Cleaned code to match FxCop 1.36 beta 2 (SpecifyMarshalingForPInvokeStringArguments, NestedTypesShouldNotBeVisible)
-//2008-04-10: NewInstanceEventArgs is not nested class anymore
-//2008-01-26: AutoExit parameter changed to NoAutoExit
-//2008-01-08: Main method is now called Attach
-//2008-01-06: System.Environment.Exit returns E_ABORT (0x80004004)
-//2008-01-03: Added Resources
-//2007-12-29: New version
-
-#nullable enable
-
-namespace Medo.Application;
-
-using System;
-using System.Diagnostics;
-using System.IO.Pipes;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-using System.Text;
-using System.Text.Json;
-using System.Text.Json.Serialization;
-using System.Threading;
-
-using ICSharpCode.ILSpy.AppEnv;
-
-///
-/// Handles detection and communication of programs multiple instances.
-/// This class is thread safe.
-///
-public static class SingleInstance
-{
-
- private static Mutex? _mtxFirstInstance;
- private static Thread? _thread;
- private static readonly object _syncRoot = new();
-
- ///
- /// Returns true if this application is not already started.
- /// Another instance is contacted via named pipe.
- ///
- /// API call failed.
- public static bool Attach()
- {
- return Attach(false);
- }
-
- private static string[] GetILSpyCommandLineArgs()
- {
- // Note: NO Skip(1) here because .Args property on SingleInstanceArguments does this for us
- return Environment.GetCommandLineArgs().AsEnumerable()
- .Select(CommandLineTools.FullyQualifyPath)
- .ToArray();
- }
-
- ///
- /// Returns true if this application is not already started.
- /// Another instance is contacted via named pipe.
- ///
- /// If true, application will exit after informing another instance.
- /// API call failed.
- public static bool Attach(bool noAutoExit)
- {
- lock (_syncRoot)
- {
- var isFirstInstance = false;
- try
- {
- _mtxFirstInstance = new Mutex(initiallyOwned: true, @"Global\" + MutexName, out isFirstInstance);
- if (isFirstInstance == false)
- { //we need to contact previous instance
- var contentObject = new SingleInstanceArguments() {
- CommandLine = Environment.CommandLine,
- CommandLineArgs = GetILSpyCommandLineArgs(),
- };
- var contentBytes = JsonSerializer.SerializeToUtf8Bytes(contentObject);
- using var clientPipe = new NamedPipeClientStream(".",
- MutexName,
- PipeDirection.Out,
- PipeOptions.CurrentUserOnly | PipeOptions.WriteThrough);
- clientPipe.Connect();
- clientPipe.Write(contentBytes, 0, contentBytes.Length);
- }
- else
- { //there is no application already running.
- _thread = new Thread(Run) {
- Name = typeof(SingleInstance).FullName,
- IsBackground = true
- };
- _thread.Start();
- }
- }
- catch (Exception ex)
- {
- Trace.TraceWarning(ex.Message + " {Medo.Application.SingleInstance}");
- }
-
- if ((isFirstInstance == false) && (noAutoExit == false))
- {
- Trace.TraceInformation("Exit due to another instance running." + " [" + nameof(SingleInstance) + "]");
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- Environment.Exit(unchecked((int)0x80004004)); // E_ABORT(0x80004004)
- }
- else
- {
- Environment.Exit(114); // EALREADY(114)
- }
- }
-
- return isFirstInstance;
- }
- }
-
- private static string? _mutexName;
- private static string MutexName {
- get {
- lock (_syncRoot)
- {
- if (_mutexName == null)
- {
- var assembly = Assembly.GetEntryAssembly();
-
- var sbMutextName = new StringBuilder();
- var assName = assembly?.GetName().Name;
- if (assName != null)
- {
- sbMutextName.Append(assName, 0, Math.Min(assName.Length, 31));
- sbMutextName.Append('.');
- }
-
- var sbHash = new StringBuilder();
- sbHash.AppendLine(Environment.MachineName);
- sbHash.AppendLine(Environment.UserName);
- if (assembly != null)
- {
- sbHash.AppendLine(assembly.FullName);
- sbHash.AppendLine(assembly.Location);
- }
- else
- {
- var args = Environment.GetCommandLineArgs();
- if (args.Length > 0)
- { sbHash.AppendLine(args[0]); }
- }
- foreach (var b in SHA256.HashData(Encoding.UTF8.GetBytes(sbHash.ToString())))
- {
- if (sbMutextName.Length == 63)
- { sbMutextName.AppendFormat("{0:X1}", b >> 4); } // just take the first nubble
- if (sbMutextName.Length == 64)
- { break; }
- sbMutextName.AppendFormat("{0:X2}", b);
- }
- _mutexName = sbMutextName.ToString();
- }
- return _mutexName;
- }
- }
- }
-
- ///
- /// Gets whether there is another instance running.
- /// It temporary creates mutex.
- ///
- public static bool IsOtherInstanceRunning {
- get {
- lock (_syncRoot)
- {
- if (_mtxFirstInstance != null)
- {
- return false; //no other instance is running
- }
- else
- {
- var tempInstance = new Mutex(true, MutexName, out var isFirstInstance);
- tempInstance.Close();
- return (isFirstInstance == false);
- }
- }
- }
- }
-
- ///
- /// Occurs in first instance when new instance is detected.
- ///
- public static event EventHandler? NewInstanceDetected;
-
- ///
- /// Thread function.
- ///
- private static void Run()
- {
- using var serverPipe = new NamedPipeServerStream(MutexName,
- PipeDirection.In,
- maxNumberOfServerInstances: 1,
- PipeTransmissionMode.Byte,
- PipeOptions.CurrentUserOnly | PipeOptions.WriteThrough);
- while (_mtxFirstInstance != null)
- {
- try
- {
- if (!serverPipe.IsConnected)
- { serverPipe.WaitForConnection(); }
- var contentObject = JsonSerializer.Deserialize(serverPipe);
- serverPipe.Disconnect();
- if (contentObject != null)
- {
- NewInstanceDetected?.Invoke(null,
- new NewInstanceEventArgs(
- contentObject.CommandLine,
- contentObject.CommandLineArgs));
- }
- }
- catch (Exception ex)
- {
- Trace.TraceWarning(ex.Message + " [" + nameof(SingleInstance) + "]");
- Thread.Sleep(100);
- }
- }
- }
-
- [Serializable]
- private sealed record SingleInstanceArguments
- { // just a storage
- [JsonInclude]
- public required string CommandLine;
-
- [JsonInclude]
- public required string[] CommandLineArgs;
- }
-
-}
-
-///
-/// Arguments for newly detected application instance.
-///
-public sealed class NewInstanceEventArgs : EventArgs
-{
- ///
- /// Creates new instance.
- ///
- /// Command line.
- /// String array containing the command line arguments in the same format as Environment.GetCommandLineArgs.
- internal NewInstanceEventArgs(string commandLine, string[] commandLineArgs)
- {
- CommandLine = commandLine;
- _commandLineArgs = new string[commandLineArgs.Length];
- Array.Copy(commandLineArgs, _commandLineArgs, _commandLineArgs.Length);
- }
-
- ///
- /// Gets the command line.
- ///
- public string CommandLine { get; }
-
- private readonly string[] _commandLineArgs;
- ///
- /// Returns a string array containing the command line arguments.
- ///
- public string[] GetCommandLineArgs()
- {
- var argCopy = new string[_commandLineArgs.Length];
- Array.Copy(_commandLineArgs, argCopy, argCopy.Length);
- return argCopy;
- }
-
- ///
- /// Gets a string array containing the command line arguments without the name of exectuable.
- ///
- public string[] Args {
- get {
- var argCopy = new string[_commandLineArgs.Length - 1];
- Array.Copy(_commandLineArgs, 1, argCopy, 0, argCopy.Length);
- return argCopy;
- }
- }
-
-}
diff --git a/ILSpy/AssemblyTree/AssemblyListPane.xaml b/ILSpy/AssemblyTree/AssemblyListPane.xaml
deleted file mode 100644
index 0fbc2050d..000000000
--- a/ILSpy/AssemblyTree/AssemblyListPane.xaml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/ILSpy/AssemblyTree/AssemblyListPane.xaml.cs b/ILSpy/AssemblyTree/AssemblyListPane.xaml.cs
deleted file mode 100644
index e6ea4d3a1..000000000
--- a/ILSpy/AssemblyTree/AssemblyListPane.xaml.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2024 Tom Englert for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Windows;
-using System.Windows.Threading;
-
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpyX.TreeView;
-
-using TomsToolbox.Wpf;
-using TomsToolbox.Wpf.Composition.AttributedModel;
-
-namespace ICSharpCode.ILSpy.AssemblyTree
-{
- ///
- /// Interaction logic for AssemblyListPane.xaml
- ///
- [DataTemplate(typeof(AssemblyTreeModel))]
- [NonShared]
- public partial class AssemblyListPane
- {
- public AssemblyListPane()
- {
- InitializeComponent();
-
- ContextMenuProvider.Add(this);
- }
-
- protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
- {
- base.OnPropertyChanged(e);
-
- if (e.Property == DataContextProperty)
- {
- if (e.NewValue is not AssemblyTreeModel model)
- return;
-
- model.SetActiveView(this);
-
- // If there is already a selected item in the model, we need to scroll it into view, so it can be selected in the UI.
- var selected = model.SelectedItem;
- if (selected != null)
- {
- this.BeginInvoke(DispatcherPriority.Background, () => {
- ScrollIntoView(selected);
- this.SelectedItem = selected;
- });
- }
- }
- else if (e.Property == Pane.IsActiveProperty)
- {
- if (!true.Equals(e.NewValue))
- return;
-
- if (SelectedItem is SharpTreeNode selectedItem)
- {
- // defer focusing, so it does not interfere with selection via mouse click
- this.BeginInvoke(() => {
- if (this.SelectedItem == selectedItem)
- FocusNode(selectedItem);
- });
- }
- else
- {
- Focus();
- }
- }
- }
- }
-}
diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs
deleted file mode 100644
index cdcb8dac7..000000000
--- a/ILSpy/AssemblyTree/AssemblyTreeModel.cs
+++ /dev/null
@@ -1,1111 +0,0 @@
-// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.ComponentModel;
-using System.Composition;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.IO;
-using System.Linq;
-using System.Reflection.Metadata;
-using System.Reflection.Metadata.Ecma335;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Input;
-using System.Windows.Navigation;
-using System.Windows.Threading;
-
-using ICSharpCode.Decompiler.Documentation;
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.Decompiler.TypeSystem.Implementation;
-using ICSharpCode.ILSpy.AppEnv;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.Updates;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.TreeView;
-
-using TomsToolbox.Composition;
-using TomsToolbox.Essentials;
-using TomsToolbox.Wpf;
-
-#nullable enable
-
-namespace ICSharpCode.ILSpy.AssemblyTree
-{
- [ExportToolPane]
- [Shared]
- public partial class AssemblyTreeModel : ToolPaneModel
- {
- public const string PaneContentId = "assemblyListPane";
-
- private AssemblyListPane? activeView;
- private AssemblyListTreeNode? assemblyListTreeNode;
- private readonly DispatcherThrottle refreshThrottle;
-
- private readonly NavigationHistory history = new();
- private NavigationState? navigatingToState;
- private object? sourceOfReference;
- private readonly SettingsService settingsService;
- private readonly LanguageService languageService;
- private readonly IExportProvider exportProvider;
-
- private static Dispatcher UIThreadDispatcher => Application.Current.Dispatcher;
-
- private void Settings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
- {
- if (sender is SessionSettings sessionSettings)
- {
- switch (e.PropertyName)
- {
- case nameof(SessionSettings.ActiveAssemblyList):
- ShowAssemblyList(sessionSettings.ActiveAssemblyList);
- RefreshDecompiledView();
- break;
- case nameof(SessionSettings.Theme):
- // update syntax highlighting and force reload (AvalonEdit does not automatically refresh on highlighting change)
- DecompilerTextView.RegisterHighlighting();
- RefreshDecompiledView();
- break;
- case nameof(SessionSettings.CurrentCulture):
- MessageBox.Show(Resources.SettingsChangeRestartRequired, "ILSpy");
- break;
- }
- }
- else if (sender is LanguageSettings)
- {
- switch (e.PropertyName)
- {
- case nameof(LanguageSettings.LanguageId) or nameof(LanguageSettings.LanguageVersionId):
- RefreshDecompiledView();
- break;
- default:
- Refresh();
- break;
- }
- }
- }
-
- public AssemblyList AssemblyList { get; private set; }
-
- private SharpTreeNode? root;
- public SharpTreeNode? Root {
- get => root;
- set => SetProperty(ref root, value);
- }
-
- public SharpTreeNode? SelectedItem {
- get => SelectedItems.FirstOrDefault();
- set => SelectedItems = value is null ? [] : [value];
- }
-
- private SharpTreeNode[] selectedItems = [];
- public SharpTreeNode[] SelectedItems {
- get => selectedItems;
- set {
- if (selectedItems.SequenceEqual(value))
- return;
-
- var oldSelection = selectedItems;
- selectedItems = value;
- OnPropertyChanged();
-#if CROSS_PLATFORM
- OnPropertyChanged(nameof(SelectedItem));
-#endif
- TreeView_SelectionChanged(oldSelection, selectedItems);
- }
- }
-
- public string[]? SelectedPath => GetPathForNode(SelectedItem);
-
- private readonly List commandLineLoadedAssemblies = [];
-
- private bool HandleCommandLineArguments(CommandLineArguments args)
- {
- LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false);
- if (args.Language != null)
- languageService.Language = languageService.GetLanguage(args.Language);
- return true;
- }
-
- ///
- /// Called on startup or when passed arguments via WndProc from a second instance.
- /// In the format case, updateSettings is non-null; in the latter it is null.
- ///
- private async Task HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, UpdateSettings? updateSettings = null)
- {
- var sessionSettings = settingsService.SessionSettings;
-
- var relevantAssemblies = commandLineLoadedAssemblies.ToList();
- commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore
-
- await NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, updateSettings, relevantAssemblies);
-
- if (args.Search != null)
- {
- MessageBus.Send(this, new ShowSearchPageEventArgs(args.Search));
- }
- }
-
- public async Task HandleSingleInstanceCommandLineArguments(string[] args)
- {
- var cmdArgs = CommandLineArguments.Create(args);
-
- await UIThreadDispatcher.InvokeAsync(async () => {
-
- if (!HandleCommandLineArguments(cmdArgs))
- return;
-
- var window = Application.Current.MainWindow;
-
- if (!cmdArgs.NoActivate && window is { WindowState: WindowState.Minimized })
- {
- window.WindowState = WindowState.Normal;
- }
-
- await HandleCommandLineArgumentsAfterShowList(cmdArgs);
- });
- }
-
- private async Task NavigateOnLaunch(string? navigateTo, string[]? activeTreeViewPath, UpdateSettings? updateSettings, List relevantAssemblies)
- {
- var initialSelection = SelectedItem;
- if (navigateTo != null)
- {
- bool found = false;
- if (navigateTo.StartsWith("N:", StringComparison.Ordinal))
- {
- string namespaceName = navigateTo.Substring(2);
- foreach (LoadedAssembly asm in relevantAssemblies)
- {
- var asmNode = assemblyListTreeNode?.FindAssemblyNode(asm);
- if (asmNode != null)
- {
- // FindNamespaceNode() blocks the UI if the assembly is not yet loaded,
- // so use an async wait instead.
- await asm.GetMetadataFileAsync().Catch(_ => { });
- NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName);
- if (nsNode != null)
- {
- found = true;
- if (SelectedItem == initialSelection)
- {
- SelectNode(nsNode);
- }
- break;
- }
- }
- }
- }
- else if (navigateTo == "none")
- {
- // Don't navigate anywhere; start empty.
- // Used by ILSpy VS addin, it'll send us the real location to navigate to via IPC.
- found = true;
- }
- else
- {
- IEntity? mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies));
-
- // Make sure we wait for assemblies being loaded...
- // BeginInvoke in LoadedAssembly.LookupReferencedAssemblyInternal
- await UIThreadDispatcher.InvokeAsync(delegate { }, DispatcherPriority.Normal);
-
- if (mr is { ParentModule.MetadataFile: not null })
- {
- found = true;
- if (SelectedItem == initialSelection)
- {
- await JumpToReferenceAsync(mr, null);
- }
- }
- }
- if (!found && SelectedItem == initialSelection)
- {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- output.Write($"Cannot find '{navigateTo}' in command line specified assemblies.");
- DockWorkspace.ShowText(output);
- }
- }
- else if (relevantAssemblies.Count == 1)
- {
- // NavigateTo == null and an assembly was given on the command-line:
- // Select the newly loaded assembly
- var asmNode = assemblyListTreeNode?.FindAssemblyNode(relevantAssemblies[0]);
- if (asmNode != null && SelectedItem == initialSelection)
- {
- SelectNode(asmNode);
- }
- }
- else if (updateSettings != null)
- {
- SharpTreeNode? node = null;
- if (activeTreeViewPath?.Length > 0)
- {
- foreach (var asm in AssemblyList.GetAssemblies())
- {
- if (asm.FileName == activeTreeViewPath[0])
- {
- // FindNodeByPath() blocks the UI if the assembly is not yet loaded,
- // so use an async wait instead.
- await asm.GetMetadataFileAsync().Catch(_ => { });
- }
- }
- node = FindNodeByPath(activeTreeViewPath, true);
- }
- if (SelectedItem == initialSelection)
- {
- if (node != null)
- {
- SelectNode(node);
-
- // only if not showing the about page, perform the update check:
- MessageBus.Send(this, new CheckIfUpdateAvailableEventArgs());
- }
- else
- {
- MessageBus.Send(this, new ShowAboutPageEventArgs(DockWorkspace.ActiveTabPage));
- }
- }
- }
- }
-
- public static IEntity? FindEntityInRelevantAssemblies(string navigateTo, IEnumerable relevantAssemblies)
- {
- ITypeReference typeRef;
- IMemberReference? memberRef = null;
- if (navigateTo.StartsWith("T:", StringComparison.Ordinal))
- {
- typeRef = IdStringProvider.ParseTypeName(navigateTo);
- }
- else
- {
- memberRef = IdStringProvider.ParseMemberIdString(navigateTo);
- typeRef = memberRef.DeclaringTypeReference;
- }
- foreach (LoadedAssembly asm in relevantAssemblies.ToList())
- {
- var module = asm.GetMetadataFileOrNull();
- if (module != null && CanResolveTypeInPEFile(module, typeRef, out var typeHandle))
- {
- ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType
- ? new DecompilerTypeSystem(module, module.GetAssemblyResolver())
- : new SimpleCompilation((PEFile)module, MinimalCorlib.Instance);
- return memberRef == null
- ? typeRef.Resolve(new SimpleTypeResolveContext(compilation)) as ITypeDefinition
- : memberRef.Resolve(new SimpleTypeResolveContext(compilation));
- }
- }
- return null;
- }
-
- private static bool CanResolveTypeInPEFile(MetadataFile module, ITypeReference typeRef, out EntityHandle typeHandle)
- {
- // We intentionally ignore reference assemblies, so that the loop continues looking for another assembly that might have a usable definition.
- if (module.IsReferenceAssembly())
- {
- typeHandle = default;
- return false;
- }
-
- switch (typeRef)
- {
- case GetPotentiallyNestedClassTypeReference topLevelType:
- typeHandle = topLevelType.ResolveInPEFile(module);
- return !typeHandle.IsNil;
- case NestedTypeReference nestedType:
- if (!CanResolveTypeInPEFile(module, nestedType.DeclaringTypeReference, out typeHandle))
- return false;
- if (typeHandle.Kind == HandleKind.ExportedType)
- return true;
- var typeDef = module.Metadata.GetTypeDefinition((TypeDefinitionHandle)typeHandle);
- typeHandle = typeDef.GetNestedTypes().FirstOrDefault(t => {
- var td = module.Metadata.GetTypeDefinition(t);
- var typeName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(module.Metadata.GetString(td.Name), out int typeParameterCount);
- return nestedType.AdditionalTypeParameterCount == typeParameterCount && nestedType.Name == typeName;
- });
- return !typeHandle.IsNil;
- default:
- typeHandle = default;
- return false;
- }
- }
-
- public void Initialize()
- {
- AssemblyList = settingsService.LoadInitialAssemblyList();
-
- HandleCommandLineArguments(App.CommandLineArguments);
-
- var loadPreviousAssemblies = settingsService.MiscSettings.LoadPreviousAssemblies;
- if (AssemblyList.GetAssemblies().Length == 0
- && AssemblyList.ListName == AssemblyListManager.DefaultListName
- && loadPreviousAssemblies)
- {
- LoadInitialAssemblies(AssemblyList);
- }
-
- ShowAssemblyList(AssemblyList);
-
- var sessionSettings = settingsService.SessionSettings;
- if (sessionSettings.ActiveAutoLoadedAssembly != null
- && File.Exists(sessionSettings.ActiveAutoLoadedAssembly))
- {
- AssemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true);
- }
-
- UIThreadDispatcher.BeginInvoke(DispatcherPriority.Loaded, OpenAssemblies);
- }
-
- private async Task OpenAssemblies()
- {
- await HandleCommandLineArgumentsAfterShowList(App.CommandLineArguments, settingsService.GetSettings());
-
- if (FormatExceptions(App.StartupExceptions.ToArray(), out var output))
- {
- output.Title = "Startup errors";
-
- DockWorkspace.AddTabPage();
- DockWorkspace.ShowText(output);
- }
- }
-
- private static bool FormatExceptions(App.ExceptionData[] exceptions, [NotNullWhen(true)] out AvalonEditTextOutput? output)
- {
- output = null;
-
- var result = exceptions.FormatExceptions();
- if (result.IsNullOrEmpty())
- return false;
-
- output = new();
- output.Write(result);
- return true;
-
- }
-
- private void ShowAssemblyList(string name)
- {
- AssemblyList list = settingsService.AssemblyListManager.LoadList(name);
- //Only load a new list when it is a different one
- if (list.ListName != AssemblyList.ListName)
- {
- ShowAssemblyList(list);
- SelectNode(Root?.Children.FirstOrDefault());
- }
- }
-
- private void ShowAssemblyList(AssemblyList assemblyList)
- {
- history.Clear();
-
- AssemblyList.CollectionChanged -= assemblyList_CollectionChanged;
- AssemblyList = assemblyList;
- assemblyList.CollectionChanged += assemblyList_CollectionChanged;
-
- assemblyListTreeNode = new(assemblyList) {
- Select = x => SelectNode(x)
- };
-
- Root = assemblyListTreeNode;
-
- var mainWindow = Application.Current?.MainWindow;
-
- if (mainWindow == null)
- return;
-
- if (assemblyList.ListName == AssemblyListManager.DefaultListName)
-#if DEBUG
- mainWindow.Title = $"ILSpy {DecompilerVersionInfo.FullVersion}";
-#else
- mainWindow.Title = "ILSpy";
-#endif
- else
-#if DEBUG
- mainWindow.Title = string.Format(settingsService.MiscSettings.AllowMultipleInstances ? "{1} - {0}" : "{0} - {1}", $"ILSpy {DecompilerVersionInfo.FullVersion}", assemblyList.ListName);
-#else
- mainWindow.Title = string.Format(settingsService.MiscSettings.AllowMultipleInstances ? "{1} - {0}" : "{0} - {1}", "ILSpy", assemblyList.ListName);
-#endif
- }
-
- private void assemblyList_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
- {
- if (e.Action == NotifyCollectionChangedAction.Reset)
- {
- history.RemoveAll(_ => true);
- }
- if (e.OldItems != null)
- {
- var oldAssemblies = new HashSet(e.OldItems.Cast());
- history.RemoveAll(n => n.TreeNodes.Any(
- nd => nd.AncestorsAndSelf().OfType().Any(
- a => oldAssemblies.Contains(a.LoadedAssembly))));
- }
-
- MessageBus.Send(this, new CurrentAssemblyListChangedEventArgs(e));
- }
-
- public AssemblyTreeNode? FindAssemblyNode(LoadedAssembly asm)
- {
- return assemblyListTreeNode?.FindAssemblyNode(asm);
- }
-
- #region Node Selection
-
- public void SelectNode(SharpTreeNode? node, bool inNewTabPage = false)
- {
- if (node == null)
- return;
-
- if (node.AncestorsAndSelf().Any(item => item.IsHidden))
- {
- MessageBox.Show(Resources.NavigationFailed, "ILSpy", MessageBoxButton.OK, MessageBoxImage.Exclamation);
- return;
- }
-
- if (inNewTabPage)
- {
- DockWorkspace.AddTabPage();
- SelectedItem = null;
- }
-
- if (SelectedItem == node)
- {
- UIThreadDispatcher.BeginInvoke(RefreshDecompiledView);
- }
- else
- {
-#if CROSS_PLATFORM
- ExpandAncestors(node);
-#endif
- activeView?.ScrollIntoView(node);
- SelectedItem = node;
-
- UIThreadDispatcher.BeginInvoke(DispatcherPriority.Background, () => {
-#if CROSS_PLATFORM
- SelectedItem = node;
-#endif
- activeView?.ScrollIntoView(node);
- });
- }
- }
-
- public void SelectNodes(IEnumerable nodes)
- {
- // Ensure nodes exist
- var nodesList = nodes.Select(n => FindNodeByPath(GetPathForNode(n), true))
- .ExceptNullItems()
- .ToArray();
-
- if (!nodesList.Any() || nodesList.Any(n => n.AncestorsAndSelf().Any(a => a.IsHidden)))
- {
- return;
- }
-
- foreach (var node in nodesList)
- {
- activeView?.ScrollIntoView(node);
- }
-
- SelectedItems = nodesList.ToArray();
- }
-
- ///
- /// Retrieves a node using the .ToString() representations of its ancestors.
- ///
- public SharpTreeNode? FindNodeByPath(string[]? path, bool returnBestMatch)
- {
- if (path == null)
- return null;
- var node = Root;
- var bestMatch = node;
- foreach (var element in path)
- {
- if (node == null)
- break;
- bestMatch = node;
- node.EnsureLazyChildren();
- if (node is ILSpyTreeNode ilSpyTreeNode)
- ilSpyTreeNode.EnsureChildrenFiltered();
- node = node.Children.FirstOrDefault(c => c.ToString() == element);
- }
-
- return returnBestMatch ? node ?? bestMatch : node;
- }
-
- ///
- /// Gets the .ToString() representation of the node's ancestors.
- ///
- public static string[]? GetPathForNode(SharpTreeNode? node)
- {
- if (node == null)
- return null;
- List path = new List();
- while (node.Parent != null)
- {
- path.Add(node.ToString()!);
- node = node.Parent;
- }
- path.Reverse();
- return path.ToArray();
- }
-
- public ILSpyTreeNode? FindTreeNode(object? reference)
- {
- if (assemblyListTreeNode == null)
- return null;
-
- switch (reference)
- {
- case LoadedAssembly lasm:
- return assemblyListTreeNode.FindAssemblyNode(lasm);
- case MetadataFile asm:
- return assemblyListTreeNode.FindAssemblyNode(asm);
- case Resource res:
- return assemblyListTreeNode.FindResourceNode(res);
- case ValueTuple resName:
- return assemblyListTreeNode.FindResourceNode(resName.Item1, resName.Item2);
- case ITypeDefinition type:
- return assemblyListTreeNode.FindTypeNode(type);
- case IField fd:
- return assemblyListTreeNode.FindFieldNode(fd);
- case IMethod md:
- return assemblyListTreeNode.FindMethodNode(md);
- case IProperty pd:
- return assemblyListTreeNode.FindPropertyNode(pd);
- case IEvent ed:
- return assemblyListTreeNode.FindEventNode(ed);
- case INamespace nd:
- return assemblyListTreeNode.FindNamespaceNode(nd);
- default:
- return null;
- }
- }
-
- private void JumpToReference(object? sender, NavigateToReferenceEventArgs e)
- {
- JumpToReferenceAsync(e.Reference, e.Source, e.InNewTabPage).HandleExceptions();
- IsActive = true;
- }
-
- ///
- /// Jumps to the specified reference.
- ///
- ///
- /// Returns a task that will signal completion when the decompilation of the jump target has finished.
- /// The task will be marked as canceled if the decompilation is canceled.
- ///
- private Task JumpToReferenceAsync(object? reference, object? source, bool inNewTabPage = false)
- {
- this.sourceOfReference = source;
- var decompilationTask = Task.CompletedTask;
-
- switch (reference)
- {
- case Decompiler.Disassembler.OpCodeInfo opCode:
- GlobalUtils.OpenLink(opCode.Link);
- break;
- case EntityReference unresolvedEntity:
- string protocol = unresolvedEntity.Protocol;
- var file = unresolvedEntity.ResolveAssembly(AssemblyList);
- if (file == null)
- {
- break;
- }
- if (protocol != "decompile")
- {
- foreach (var handler in exportProvider.GetExportedValues())
- {
- var node = handler.Resolve(protocol, file, unresolvedEntity.Handle, out bool newTabPage);
- if (node != null)
- {
- SelectNode(node, newTabPage || inNewTabPage);
- return decompilationTask;
- }
- }
- }
- var possibleToken = MetadataTokenHelpers.TryAsEntityHandle(MetadataTokens.GetToken(unresolvedEntity.Handle));
- if (possibleToken != null)
- {
- var typeSystem = new DecompilerTypeSystem(file, file.GetAssemblyResolver(), TypeSystemOptions.Default | TypeSystemOptions.Uncached);
- reference = typeSystem.MainModule.ResolveEntity(possibleToken.Value);
- goto default;
- }
- break;
- default:
- var treeNode = FindTreeNode(reference);
- if (treeNode != null)
- SelectNode(treeNode, inNewTabPage);
- break;
- }
- return decompilationTask;
- }
-
- #endregion
-
- private void LoadAssemblies(IEnumerable fileNames, List? loadedAssemblies = null, bool focusNode = true)
- {
- using (Keyboard.FocusedElement.PreserveFocus(!focusNode))
- {
- AssemblyTreeNode? lastNode = null;
-
- var assemblyList = AssemblyList;
-
- foreach (string file in fileNames)
- {
- var assembly = assemblyList.OpenAssembly(file);
-
- if (loadedAssemblies != null)
- {
- loadedAssemblies.Add(assembly);
- }
- else
- {
- var node = assemblyListTreeNode?.FindAssemblyNode(assembly);
- if (node != null && focusNode)
- {
- lastNode = node;
- activeView?.ScrollIntoView(node);
- SelectedItems = [.. SelectedItems, node];
- }
- }
- }
- if (focusNode && lastNode != null)
- {
- activeView?.FocusNode(lastNode);
- }
- }
- }
-
- #region Decompile (TreeView_SelectionChanged)
-
- private void TreeView_SelectionChanged(SharpTreeNode[] oldSelection, SharpTreeNode[] newSelection)
- {
- var activeTabPage = DockWorkspace.ActiveTabPage;
- ViewState? oldState = activeTabPage.GetState();
- ViewState? newState;
-
- if (navigatingToState == null)
- {
- if (oldState != null)
- {
- history.UpdateCurrent(new NavigationState(activeTabPage, oldState));
- }
-
- newState = new ViewState { DecompiledNodes = [.. newSelection.Cast()] };
- }
- else
- {
- newState = navigatingToState.ViewState;
- }
-
- if (newSelection.Length == 0)
- {
- // To cancel any pending decompilation requests and show an empty tab
- DecompileSelectedNodes(newState);
- }
- else
- {
- var delayDecompilationRequestDueToContextMenu = Mouse.RightButton == MouseButtonState.Pressed;
-
- if (!delayDecompilationRequestDueToContextMenu)
- {
- var previousNodes = oldState?.DecompiledNodes
- ?.Select(n => FindNodeByPath(GetPathForNode(n), true))
- .ExceptNullItems()
- .ToArray() ?? [];
-
- if (!previousNodes.SequenceEqual(SelectedItems))
- {
- DecompileSelectedNodes(newState);
- }
- }
- else
- {
- // ensure that we are only connected once to the event, else we might get multiple notifications
- ContextMenuProvider.ContextMenuClosed -= ContextMenuClosed;
- ContextMenuProvider.ContextMenuClosed += ContextMenuClosed;
- }
- }
-
- MessageBus.Send(this, new AssemblyTreeSelectionChangedEventArgs());
-
- return;
-
- void ContextMenuClosed(object? sender, EventArgs e)
- {
- ContextMenuProvider.ContextMenuClosed -= ContextMenuClosed;
-
- UIThreadDispatcher.BeginInvoke(DispatcherPriority.Background, () => {
- if (Mouse.RightButton != MouseButtonState.Pressed)
- {
- RefreshDecompiledView();
- }
- });
- }
- }
-
- public void DecompileSelectedNodes(ViewState? newState = null)
- {
- object? source = this.sourceOfReference;
- this.sourceOfReference = null;
- var activeTabPage = DockWorkspace.ActiveTabPage;
-
- if (activeTabPage.FrozenContent)
- {
- activeTabPage = DockWorkspace.AddTabPage();
- }
-
- activeTabPage.SupportsLanguageSwitching = true;
-
- if (newState != null && navigatingToState == null)
- {
- history.Record(new NavigationState(activeTabPage, newState));
- }
-
- if (SelectedItems.Length == 1)
- {
- if (SelectedItem is ILSpyTreeNode node && node.View(activeTabPage))
- return;
- }
- if (newState?.ViewedUri != null)
- {
- NavigateTo(new(newState.ViewedUri, null));
- return;
- }
-
- var options = activeTabPage.CreateDecompilationOptions();
- options.TextViewState = newState as DecompilerTextViewState;
- activeTabPage.ShowTextViewAsync(textView => {
- return textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, source, options);
- });
- }
-
- public void RefreshDecompiledView()
- {
- DecompileSelectedNodes(DockWorkspace.ActiveTabPage.GetState() as DecompilerTextViewState);
- }
-
- public Language CurrentLanguage => languageService.Language;
-
- public LanguageVersion? CurrentLanguageVersion => languageService.LanguageVersion;
-
- public IEnumerable SelectedNodes => GetTopLevelSelection().OfType();
-
- #endregion
-
- public void NavigateHistory(bool forward, NavigationState? toState = null)
- {
- try
- {
- TabPageModel tabPage = DockWorkspace.ActiveTabPage;
- var currentState = tabPage.GetState();
- if (currentState != null)
- history.UpdateCurrent(new NavigationState(tabPage, currentState));
-
- NavigationState newState;
- do
- {
- newState = forward ? history.GoForward() : history.GoBack();
- } while (newState != null && toState != null && toState != newState);
-
- if (newState == null)
- return;
-
- navigatingToState = newState;
-
- TabPageModel activeTabPage = newState.TabPage;
-
- Debug.Assert(DockWorkspace.TabPages.Contains(activeTabPage));
- DockWorkspace.ActiveTabPage = activeTabPage;
-
- if (newState.TreeNodes.Any())
- {
- SelectNodes(newState.TreeNodes);
- }
- else if (newState.ViewState.ViewedUri != null)
- {
- NavigateTo(new(newState.ViewState.ViewedUri, null));
- }
- }
- finally
- {
- navigatingToState = null;
- }
- }
-
- public NavigationState[] GetNavigateHistory(bool forward) => forward ? history.ForwardList : history.BackList;
-
- public bool CanNavigateBack => history.CanNavigateBack;
-
- public bool CanNavigateForward => history.CanNavigateForward;
-
- private void NavigateTo(RequestNavigateEventArgs e, bool inNewTabPage = false)
- {
- if (e.Uri.Scheme != "resource")
- {
- return;
- }
-
- TabPageModel tabPage = DockWorkspace.ActiveTabPage;
- ViewState? oldState = tabPage.GetState();
- ViewState? newState;
-
- if (navigatingToState == null)
- {
- if (oldState != null)
- {
- history.UpdateCurrent(new NavigationState(tabPage, oldState));
- }
-
- newState = new ViewState { ViewedUri = e.Uri };
-
- if (inNewTabPage)
- {
- tabPage = DockWorkspace.AddTabPage();
- }
- }
- else
- {
- newState = navigatingToState.ViewState;
- tabPage = DockWorkspace.ActiveTabPage = navigatingToState.TabPage;
- }
-
- bool needsNewNavigationEntry = !inNewTabPage && selectedItems?.Length == 0;
-
- UnselectAll();
-
- if (e.Uri.Host == "aboutpage")
- {
- MessageBus.Send(this, new ShowAboutPageEventArgs(DockWorkspace.ActiveTabPage));
- e.Handled = true;
- }
- else
- {
- AvalonEditTextOutput output = new AvalonEditTextOutput {
- Address = e.Uri,
- Title = e.Uri.AbsolutePath,
- EnableHyperlinks = true
- };
- using (Stream? s = typeof(App).Assembly.GetManifestResourceStream(typeof(App), e.Uri.AbsolutePath))
- {
- if (s != null)
- {
- using StreamReader r = new StreamReader(s);
- string? line;
- while ((line = r.ReadLine()) != null)
- {
- output.Write(line);
- output.WriteLine();
- }
- }
- }
- DockWorkspace.ShowText(output);
- e.Handled = true;
- }
-
- if (navigatingToState == null)
- {
- // the call to UnselectAll() above already creates a new navigation entry,
- // we just need to make sure it contains something useful.
- if (!needsNewNavigationEntry)
- {
- history.UpdateCurrent(new NavigationState(tabPage, tabPage.GetState()));
- }
- else
- {
- history.Record(new NavigationState(tabPage, tabPage.GetState()));
- }
- }
- }
-
- public void Refresh()
- {
- refreshThrottle.Tick();
- }
-
- private void RefreshInternal()
- {
- RefreshInternalAsync().HandleExceptions();
- }
-
- private async Task RefreshInternalAsync()
- {
- using (Keyboard.FocusedElement.PreserveFocus())
- {
- var path = GetPathForNode(SelectedItem);
-
- ShowAssemblyList(settingsService.AssemblyListManager.LoadList(AssemblyList.ListName));
-
- // Ensure the assembly is loaded before FindNodeByPath, so lazy-loaded
- // resource nodes (e.g. .baml entries) are present in the tree.
- if (path?.Length > 0)
- {
- var rootAssembly = AssemblyList.FindAssembly(path[0]);
- if (rootAssembly != null)
- {
- // FindNodeByPath() blocks the UI if the assembly is not yet loaded,
- // so use an async wait instead.
- var preAwaitSelection = SelectedItem;
- await rootAssembly.GetMetadataFileAsync().Catch(_ => { });
-
- // If the user navigated to a different node while the assembly
- // was loading, respect that — don't restore the pre-refresh path.
- // A change to null counts too (e.g. user cleared the selection).
- if (!ReferenceEquals(SelectedItem, preAwaitSelection))
- {
- RefreshDecompiledView();
- return;
- }
- }
- }
-
- SelectNode(FindNodeByPath(path, true), inNewTabPage: false);
-
- RefreshDecompiledView();
- }
- }
-
- private void UnselectAll()
- {
- SelectedItems = [];
- }
-
- private IEnumerable GetTopLevelSelection()
- {
- var selection = this.SelectedItems;
- var selectionHash = new HashSet(selection);
-
- return selection.Where(item => item.Ancestors().All(a => !selectionHash.Contains(a)));
- }
-
- void ExpandAncestors(SharpTreeNode node)
- {
- foreach (var ancestor in node.Ancestors().Reverse())
- {
- ancestor.EnsureLazyChildren();
- ancestor.IsExpanded = true;
- }
- }
-
- public void SetActiveView(AssemblyListPane activeView)
- {
- this.activeView = activeView;
- }
-
- public void SortAssemblyList()
- {
- using (activeView?.LockUpdates())
- {
- AssemblyList.Sort(AssemblyComparer.Instance);
- }
- }
-
- private class AssemblyComparer : IComparer
- {
- public static readonly AssemblyComparer Instance = new();
- int IComparer.Compare(LoadedAssembly? x, LoadedAssembly? y)
- {
- return string.Compare(x?.ShortName, y?.ShortName, StringComparison.CurrentCulture);
- }
- }
-
- public void CollapseAll()
- {
- using (activeView?.LockUpdates())
- {
- CollapseChildren(Root);
- }
- }
-
- private static void CollapseChildren(SharpTreeNode? node)
- {
- if (node is null)
- return;
-
- foreach (var child in node.Children)
- {
- if (!child.IsExpanded)
- continue;
-
- CollapseChildren(child);
- child.IsExpanded = false;
- }
- }
-
- public void OpenFiles(string[] fileNames, bool focusNode = true)
- {
- if (fileNames == null)
- throw new ArgumentNullException(nameof(fileNames));
-
- if (focusNode)
- UnselectAll();
-
- LoadAssemblies(fileNames, focusNode: focusNode);
- }
-
- private void ApplySessionSettings(object? sender, ApplySessionSettingsEventArgs e)
- {
- var settings = e.SessionSettings;
-
- settings.ActiveAssemblyList = AssemblyList.ListName;
- settings.ActiveTreeViewPath = SelectedPath;
- settings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(SelectedItem);
- }
-
- private static string? GetAutoLoadedAssemblyNode(SharpTreeNode? node)
- {
- var assemblyTreeNode = node?
- .AncestorsAndSelf()
- .OfType()
- .FirstOrDefault();
-
- var loadedAssembly = assemblyTreeNode?.LoadedAssembly;
-
- return loadedAssembly is not { IsLoaded: true, IsAutoLoaded: true }
- ? null
- : loadedAssembly.FileName;
- }
-
- private void ActiveTabPageChanged(object? sender, ActiveTabPageChangedEventArgs e)
- {
- if (e.ViewState is not { } state)
- return;
-
- if (state.DecompiledNodes != null)
- {
- SelectNodes(state.DecompiledNodes);
- }
- else
- {
- NavigateTo(new(state.ViewedUri, null));
- }
- }
-
- private void ResetLayout(object? sender, ResetLayoutEventArgs e)
- {
- RefreshDecompiledView();
- }
- }
-}
diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.wpf.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.wpf.cs
deleted file mode 100644
index 9c3f49cb1..000000000
--- a/ILSpy/AssemblyTree/AssemblyTreeModel.wpf.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Windows;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Navigation;
-using System.Windows.Threading;
-
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpyX;
-
-using TomsToolbox.Composition;
-
-namespace ICSharpCode.ILSpy.AssemblyTree
-{
- public partial class AssemblyTreeModel
- {
- public AssemblyTreeModel(SettingsService settingsService, LanguageService languageService, IExportProvider exportProvider)
- {
- this.settingsService = settingsService;
- this.languageService = languageService;
- this.exportProvider = exportProvider;
-
- Title = Resources.Assemblies;
- ContentId = PaneContentId;
- IsCloseable = false;
- ShortcutKey = new KeyGesture(Key.F6);
-
- MessageBus.Subscribers += JumpToReference;
- MessageBus.Subscribers += (sender, e) => Settings_PropertyChanged(sender, e);
- MessageBus.Subscribers += ApplySessionSettings;
- MessageBus.Subscribers += ActiveTabPageChanged;
- MessageBus.Subscribers += (_, e) => history.RemoveAll(s => !DockWorkspace.TabPages.Contains(s.TabPage));
- MessageBus.Subscribers += ResetLayout;
- MessageBus.Subscribers += (_, e) => NavigateTo(e.Request, e.InNewTabPage);
- MessageBus.Subscribers += (_, _) => {
- Initialize();
- Show();
- };
-
- EventManager.RegisterClassHandler(typeof(Window), Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler((_, e) => NavigateTo(e)));
-
- refreshThrottle = new(DispatcherPriority.Background, RefreshInternal);
-
- AssemblyList = settingsService.CreateEmptyAssemblyList();
- }
-
- private static void LoadInitialAssemblies(AssemblyList assemblyList)
- {
- // Called when loading an empty assembly list; so that
- // the user can see something initially.
- System.Reflection.Assembly[] initialAssemblies = {
- typeof(object).Assembly,
- typeof(Uri).Assembly,
- typeof(System.Linq.Enumerable).Assembly,
- typeof(System.Xml.XmlDocument).Assembly,
- typeof(System.Windows.Markup.MarkupExtension).Assembly,
- typeof(System.Windows.Rect).Assembly,
- typeof(System.Windows.UIElement).Assembly,
- typeof(System.Windows.FrameworkElement).Assembly
- };
- foreach (System.Reflection.Assembly asm in initialAssemblies)
- assemblyList.OpenAssembly(asm.Location);
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/AvalonEdit/ITextMarker.cs b/ILSpy/AvalonEdit/ITextMarker.cs
deleted file mode 100644
index ec7c5c93b..000000000
--- a/ILSpy/AvalonEdit/ITextMarker.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Windows;
-using System.Windows.Media;
-
-namespace ICSharpCode.ILSpy.AvalonEdit
-{
- ///
- /// Represents a text marker.
- ///
- public interface ITextMarker
- {
- ///
- /// Gets the start offset of the marked text region.
- ///
- int StartOffset { get; }
-
- ///
- /// Gets the end offset of the marked text region.
- ///
- int EndOffset { get; }
-
- ///
- /// Gets the length of the marked region.
- ///
- int Length { get; }
-
- ///
- /// Deletes the text marker.
- ///
- void Delete();
-
- ///
- /// Gets whether the text marker was deleted.
- ///
- bool IsDeleted { get; }
-
- ///
- /// Event that occurs when the text marker is deleted.
- ///
- event EventHandler Deleted;
-
- ///
- /// Gets/Sets the background color.
- ///
- Color? BackgroundColor { get; set; }
-
- ///
- /// Gets/Sets the foreground color.
- ///
- Color? ForegroundColor { get; set; }
-
- ///
- /// Gets/Sets the font weight.
- ///
- FontWeight? FontWeight { get; set; }
-
- ///
- /// Gets/Sets the font style.
- ///
- FontStyle? FontStyle { get; set; }
-
- ///
- /// Gets/Sets the type of the marker. Use TextMarkerType.None for normal markers.
- ///
- TextMarkerTypes MarkerTypes { get; set; }
-
- ///
- /// Gets/Sets the color of the marker.
- ///
- Color MarkerColor { get; set; }
-
- ///
- /// Gets/Sets an object with additional data for this text marker.
- ///
- object Tag { get; set; }
-
- ///
- /// Gets/Sets an object that will be displayed as tooltip in the text editor.
- ///
- object ToolTip { get; set; }
- }
-
- [Flags]
- public enum TextMarkerTypes
- {
- ///
- /// Use no marker
- ///
- None = 0x0000,
- ///
- /// Use squiggly underline marker
- ///
- SquigglyUnderline = 0x001,
- ///
- /// Normal underline.
- ///
- NormalUnderline = 0x002,
- ///
- /// Dotted underline.
- ///
- DottedUnderline = 0x004,
-
- ///
- /// Horizontal line in the scroll bar.
- ///
- LineInScrollBar = 0x0100,
- ///
- /// Small triangle in the scroll bar, pointing to the right.
- ///
- ScrollBarRightTriangle = 0x0400,
- ///
- /// Small triangle in the scroll bar, pointing to the left.
- ///
- ScrollBarLeftTriangle = 0x0800,
- ///
- /// Small circle in the scroll bar.
- ///
- CircleInScrollBar = 0x1000
- }
-
- public interface ITextMarkerService
- {
- ///
- /// Creates a new text marker. The text marker will be invisible at first,
- /// you need to set one of the Color properties to make it visible.
- ///
- ITextMarker Create(int startOffset, int length);
-
- ///
- /// Gets the list of text markers.
- ///
- IEnumerable TextMarkers { get; }
-
- ///
- /// Removes the specified text marker.
- ///
- void Remove(ITextMarker marker);
-
- ///
- /// Removes all text markers that match the condition.
- ///
- void RemoveAll(Predicate predicate);
-
- ///
- /// Finds all text markers at the specified offset.
- ///
- IEnumerable GetMarkersAtOffset(int offset);
- }
-}
diff --git a/ILSpy/AvalonEdit/TextMarkerService.cs b/ILSpy/AvalonEdit/TextMarkerService.cs
deleted file mode 100644
index bffac5f54..000000000
--- a/ILSpy/AvalonEdit/TextMarkerService.cs
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows;
-using System.Windows.Media;
-using System.Windows.Threading;
-
-using ICSharpCode.AvalonEdit.Document;
-using ICSharpCode.AvalonEdit.Rendering;
-
-namespace ICSharpCode.ILSpy.AvalonEdit
-{
- using TextView = ICSharpCode.AvalonEdit.Rendering.TextView;
- ///
- /// Handles the text markers for a code editor.
- ///
- sealed class TextMarkerService : DocumentColorizingTransformer, IBackgroundRenderer, ITextMarkerService
- {
- TextSegmentCollection markers;
- TextView textView;
-
- public TextMarkerService(TextView textView)
- {
- if (textView == null)
- throw new ArgumentNullException(nameof(textView));
- this.textView = textView;
- textView.DocumentChanged += OnDocumentChanged;
- OnDocumentChanged(null, null);
- }
-
- void OnDocumentChanged(object sender, EventArgs e)
- {
- if (textView.Document != null)
- markers = new TextSegmentCollection(textView.Document);
- else
- markers = null;
- }
-
- #region ITextMarkerService
- public ITextMarker Create(int startOffset, int length)
- {
- if (markers == null)
- throw new InvalidOperationException("Cannot create a marker when not attached to a document");
-
- int textLength = textView.Document.TextLength;
- if (startOffset < 0 || startOffset > textLength)
- throw new ArgumentOutOfRangeException(nameof(startOffset), startOffset, "Value must be between 0 and " + textLength);
- if (length < 0 || startOffset + length > textLength)
- throw new ArgumentOutOfRangeException(nameof(length), length, "length must not be negative and startOffset+length must not be after the end of the document");
-
- TextMarker m = new TextMarker(this, startOffset, length);
- markers.Add(m);
- // no need to mark segment for redraw: the text marker is invisible until a property is set
- return m;
- }
-
- public IEnumerable GetMarkersAtOffset(int offset)
- {
- if (markers == null)
- return Enumerable.Empty();
- else
- return markers.FindSegmentsContaining(offset);
- }
-
- public IEnumerable TextMarkers {
- get { return markers ?? Enumerable.Empty(); }
- }
-
- public void RemoveAll(Predicate predicate)
- {
- if (predicate == null)
- throw new ArgumentNullException(nameof(predicate));
- if (markers != null)
- {
- foreach (TextMarker m in markers.ToArray())
- {
- if (predicate(m))
- Remove(m);
- }
- }
- }
-
- public void Remove(ITextMarker marker)
- {
- if (marker == null)
- throw new ArgumentNullException(nameof(marker));
- TextMarker m = marker as TextMarker;
- if (markers != null && markers.Remove(m))
- {
- Redraw(m);
- m.OnDeleted();
- }
- }
-
- ///
- /// Redraws the specified text segment.
- ///
- internal void Redraw(ISegment segment)
- {
- textView.Redraw(segment, DispatcherPriority.Normal);
- RedrawRequested?.Invoke(this, EventArgs.Empty);
- }
-
- public event EventHandler RedrawRequested;
- #endregion
-
- #region DocumentColorizingTransformer
- protected override void ColorizeLine(DocumentLine line)
- {
- if (markers == null)
- return;
- int lineStart = line.Offset;
- int lineEnd = lineStart + line.Length;
- foreach (TextMarker marker in markers.FindOverlappingSegments(lineStart, line.Length))
- {
- Brush foregroundBrush = null;
- if (marker.ForegroundColor != null)
- {
- foregroundBrush = new SolidColorBrush(marker.ForegroundColor.Value);
- foregroundBrush.Freeze();
- }
- ChangeLinePart(
- Math.Max(marker.StartOffset, lineStart),
- Math.Min(marker.EndOffset, lineEnd),
- element => {
- if (foregroundBrush != null)
- {
- element.TextRunProperties.SetForegroundBrush(foregroundBrush);
- }
- Typeface tf = element.TextRunProperties.Typeface;
- element.TextRunProperties.SetTypeface(new Typeface(
- tf.FontFamily,
- marker.FontStyle ?? tf.Style,
- marker.FontWeight ?? tf.Weight,
- tf.Stretch
- ));
- }
- );
- }
- }
- #endregion
-
- #region IBackgroundRenderer
- public KnownLayer Layer {
- get {
- // draw behind selection
- return KnownLayer.Selection;
- }
- }
-
- public void Draw(ICSharpCode.AvalonEdit.Rendering.TextView textView, DrawingContext drawingContext)
- {
- if (textView == null)
- throw new ArgumentNullException(nameof(textView));
- if (drawingContext == null)
- throw new ArgumentNullException(nameof(drawingContext));
- if (markers == null || !textView.VisualLinesValid)
- return;
- var visualLines = textView.VisualLines;
- if (visualLines.Count == 0)
- return;
- int viewStart = visualLines.First().FirstDocumentLine.Offset;
- int viewEnd = visualLines.Last().LastDocumentLine.EndOffset;
- foreach (TextMarker marker in markers.FindOverlappingSegments(viewStart, viewEnd - viewStart))
- {
- if (marker.BackgroundColor != null)
- {
- BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder();
- geoBuilder.AlignToWholePixels = true;
- geoBuilder.CornerRadius = 3;
- geoBuilder.AddSegment(textView, marker);
- Geometry geometry = geoBuilder.CreateGeometry();
- if (geometry != null)
- {
- Color color = marker.BackgroundColor.Value;
- SolidColorBrush brush = new SolidColorBrush(color);
- brush.Freeze();
- drawingContext.DrawGeometry(brush, null, geometry);
- }
- }
- var underlineMarkerTypes = TextMarkerTypes.SquigglyUnderline | TextMarkerTypes.NormalUnderline | TextMarkerTypes.DottedUnderline;
- if ((marker.MarkerTypes & underlineMarkerTypes) != 0)
- {
- foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker))
- {
- Point startPoint = r.BottomLeft;
- Point endPoint = r.BottomRight;
-
- Brush usedBrush = new SolidColorBrush(marker.MarkerColor);
- usedBrush.Freeze();
- if ((marker.MarkerTypes & TextMarkerTypes.SquigglyUnderline) != 0)
- {
- double offset = 2.5;
-
- int count = Math.Max((int)((endPoint.X - startPoint.X) / offset) + 1, 4);
-
- StreamGeometry geometry = new StreamGeometry();
-
- using (StreamGeometryContext ctx = geometry.Open())
- {
- ctx.BeginFigure(startPoint, false, false);
- ctx.PolyLineTo(CreatePoints(startPoint, endPoint, offset, count).ToArray(), true, false);
- }
-
- geometry.Freeze();
-
- Pen usedPen = new Pen(usedBrush, 1);
- usedPen.Freeze();
- drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry);
- }
- if ((marker.MarkerTypes & TextMarkerTypes.NormalUnderline) != 0)
- {
- Pen usedPen = new Pen(usedBrush, 1);
- usedPen.Freeze();
- drawingContext.DrawLine(usedPen, startPoint, endPoint);
- }
- if ((marker.MarkerTypes & TextMarkerTypes.DottedUnderline) != 0)
- {
- Pen usedPen = new Pen(usedBrush, 1);
- usedPen.DashStyle = DashStyles.Dot;
- usedPen.Freeze();
- drawingContext.DrawLine(usedPen, startPoint, endPoint);
- }
- }
- }
- }
- }
-
- IEnumerable CreatePoints(Point start, Point end, double offset, int count)
- {
- for (int i = 0; i < count; i++)
- yield return new Point(start.X + i * offset, start.Y - ((i + 1) % 2 == 0 ? offset : 0));
- }
- #endregion
- }
-
- sealed class TextMarker : TextSegment, ITextMarker
- {
- readonly TextMarkerService service;
-
- public TextMarker(TextMarkerService service, int startOffset, int length)
- {
- if (service == null)
- throw new ArgumentNullException(nameof(service));
- this.service = service;
- this.StartOffset = startOffset;
- this.Length = length;
- this.markerTypes = TextMarkerTypes.None;
- }
-
- public event EventHandler Deleted;
-
- public bool IsDeleted {
- get { return !this.IsConnectedToCollection; }
- }
-
- public void Delete()
- {
- service.Remove(this);
- }
-
- internal void OnDeleted()
- {
- Deleted?.Invoke(this, EventArgs.Empty);
- }
-
- void Redraw()
- {
- service.Redraw(this);
- }
-
- Color? backgroundColor;
-
- public Color? BackgroundColor {
- get { return backgroundColor; }
- set {
- if (backgroundColor != value)
- {
- backgroundColor = value;
- Redraw();
- }
- }
- }
-
- Color? foregroundColor;
-
- public Color? ForegroundColor {
- get { return foregroundColor; }
- set {
- if (foregroundColor != value)
- {
- foregroundColor = value;
- Redraw();
- }
- }
- }
-
- FontWeight? fontWeight;
-
- public FontWeight? FontWeight {
- get { return fontWeight; }
- set {
- if (fontWeight != value)
- {
- fontWeight = value;
- Redraw();
- }
- }
- }
-
- FontStyle? fontStyle;
-
- public FontStyle? FontStyle {
- get { return fontStyle; }
- set {
- if (fontStyle != value)
- {
- fontStyle = value;
- Redraw();
- }
- }
- }
-
- public object Tag { get; set; }
-
- TextMarkerTypes markerTypes;
-
- public TextMarkerTypes MarkerTypes {
- get { return markerTypes; }
- set {
- if (markerTypes != value)
- {
- markerTypes = value;
- Redraw();
- }
- }
- }
-
- Color markerColor;
-
- public Color MarkerColor {
- get { return markerColor; }
- set {
- if (markerColor != value)
- {
- markerColor = value;
- Redraw();
- }
- }
- }
-
- public object ToolTip { get; set; }
- }
-}
diff --git a/ILSpy/Commands/BrowseBackCommand.cs b/ILSpy/Commands/BrowseBackCommand.cs
deleted file mode 100644
index 2db604b65..000000000
--- a/ILSpy/Commands/BrowseBackCommand.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Collections;
-using System.Composition;
-using System.Linq;
-using System.Windows.Input;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportToolbarCommand(ToolTip = nameof(Resources.Back), ToolbarIcon = "Images/Back", ToolbarCategory = nameof(Resources.Navigation), ToolbarOrder = 0)]
- [Shared]
- sealed class BrowseBackCommand : CommandWrapper, IProvideParameterList
- {
- readonly AssemblyTreeModel assemblyTreeModel;
-
- public BrowseBackCommand(AssemblyTreeModel assemblyTreeModel)
- : base(NavigationCommands.BrowseBack)
- {
- this.assemblyTreeModel = assemblyTreeModel;
- }
-
- protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- base.OnCanExecute(sender, e);
-
- e.Handled = true;
- e.CanExecute = assemblyTreeModel.CanNavigateBack;
- }
-
- protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
- {
- if (assemblyTreeModel.CanNavigateBack)
- {
- e.Handled = true;
- assemblyTreeModel.NavigateHistory(false, e.Parameter as NavigationState);
- }
- }
-
- public IEnumerable ParameterList => assemblyTreeModel.GetNavigateHistory(false).Reverse();
-
- public object GetParameterText(object parameter)
- {
- return (parameter as NavigationState)?.NavigationText;
- }
- }
-}
diff --git a/ILSpy/Commands/BrowseForwardCommand.cs b/ILSpy/Commands/BrowseForwardCommand.cs
deleted file mode 100644
index 022c74936..000000000
--- a/ILSpy/Commands/BrowseForwardCommand.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Collections;
-using System.Composition;
-using System.Linq;
-using System.Windows.Input;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportToolbarCommand(ToolTip = nameof(Resources.Forward), ToolbarIcon = "Images/Forward", ToolbarCategory = nameof(Resources.Navigation), ToolbarOrder = 1)]
- [Shared]
- sealed class BrowseForwardCommand : CommandWrapper, IProvideParameterList
- {
- private readonly AssemblyTreeModel assemblyTreeModel;
-
- public BrowseForwardCommand(AssemblyTreeModel assemblyTreeModel)
- : base(NavigationCommands.BrowseForward)
- {
- this.assemblyTreeModel = assemblyTreeModel;
- }
-
- protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- base.OnCanExecute(sender, e);
-
- e.Handled = true;
- e.CanExecute = assemblyTreeModel.CanNavigateForward;
- }
-
- protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
- {
- if (assemblyTreeModel.CanNavigateForward)
- {
- e.Handled = true;
- assemblyTreeModel.NavigateHistory(true, e.Parameter as NavigationState);
- }
- }
-
- public IEnumerable ParameterList => assemblyTreeModel.GetNavigateHistory(true).Reverse();
-
- public object GetParameterText(object parameter)
- {
- return (parameter as NavigationState)?.NavigationText;
- }
- }
-}
diff --git a/ILSpy/Commands/CheckForUpdatesCommand.cs b/ILSpy/Commands/CheckForUpdatesCommand.cs
deleted file mode 100644
index ed5744106..000000000
--- a/ILSpy/Commands/CheckForUpdatesCommand.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._Help), Header = nameof(Resources._CheckUpdates), MenuOrder = 5000)]
- [Shared]
- sealed class CheckForUpdatesCommand : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- MessageBus.Send(this, new CheckIfUpdateAvailableEventArgs(notify: true));
- }
- }
-}
diff --git a/ILSpy/Commands/CommandWrapper.cs b/ILSpy/Commands/CommandWrapper.cs
deleted file mode 100644
index 809184391..000000000
--- a/ILSpy/Commands/CommandWrapper.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Windows;
-using System.Windows.Input;
-
-namespace ICSharpCode.ILSpy
-{
- abstract class CommandWrapper : ICommand
- {
- private readonly ICommand wrappedCommand;
-
- protected CommandWrapper(ICommand wrappedCommand)
- {
- this.wrappedCommand = wrappedCommand;
-
- Application.Current.MainWindow?.CommandBindings.Add(new CommandBinding(wrappedCommand, OnExecute, OnCanExecute));
- }
-
- public static ICommand Unwrap(ICommand command)
- {
- if (command is CommandWrapper w)
- return w.wrappedCommand;
-
- return command;
- }
-
- public event EventHandler CanExecuteChanged {
- add { wrappedCommand.CanExecuteChanged += value; }
- remove { wrappedCommand.CanExecuteChanged -= value; }
- }
-
- public void Execute(object parameter)
- {
- wrappedCommand.Execute(parameter);
- }
-
- public bool CanExecute(object parameter)
- {
- return wrappedCommand.CanExecute(parameter);
- }
-
- protected abstract void OnExecute(object sender, ExecutedRoutedEventArgs e);
-
- protected virtual void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- e.CanExecute = true;
- }
- }
-}
diff --git a/ILSpy/Commands/CompareContextMenuEntry.cs b/ILSpy/Commands/CompareContextMenuEntry.cs
deleted file mode 100644
index 0d5e10630..000000000
--- a/ILSpy/Commands/CompareContextMenuEntry.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2025 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Threading.Tasks;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpy.Views;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportContextMenuEntry(Header = "Compare...", Order = 9999)]
- [Shared]
- internal sealed class CompareContextMenuEntry(AssemblyTreeModel assemblyTreeModel, DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- var left = ((AssemblyTreeNode)context.SelectedTreeNodes[0]).LoadedAssembly;
- var right = ((AssemblyTreeNode)context.SelectedTreeNodes[1]).LoadedAssembly;
-
- var tabPage = dockWorkspace.AddTabPage();
- CompareViewModel.Show(tabPage, left, right, assemblyTreeModel);
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- return true;
- }
-
- public bool IsVisible(TextViewContext context)
- {
- return context.SelectedTreeNodes is [AssemblyTreeNode { LoadedAssembly.IsLoadedAsValidAssembly: true }, AssemblyTreeNode { LoadedAssembly.IsLoadedAsValidAssembly: true }];
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs b/ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs
deleted file mode 100644
index 682d2cd75..000000000
--- a/ILSpy/Commands/CopyFullyQualifiedNameContextMenuEntry.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-using System.Composition;
-using System.Windows;
-
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportContextMenuEntry(Header = nameof(Resources.CopyName), Icon = "images/Copy", Order = 9999)]
- [Shared]
- public class CopyFullyQualifiedNameContextMenuEntry : IContextMenuEntry
- {
- public bool IsVisible(TextViewContext context)
- {
- return GetMemberNodeFromContext(context) != null;
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public void Execute(TextViewContext context)
- {
- var member = GetMemberNodeFromContext(context)?.Member;
- if (member == null)
- return;
- Clipboard.SetText(member.ReflectionName);
- }
-
- private IMemberTreeNode GetMemberNodeFromContext(TextViewContext context)
- {
- return context.SelectedTreeNodes?.Length == 1 ? context.SelectedTreeNodes[0] as IMemberTreeNode : null;
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Commands/CreateDiagramContextMenuEntry.cs b/ILSpy/Commands/CreateDiagramContextMenuEntry.cs
deleted file mode 100644
index 1e2240a0e..000000000
--- a/ILSpy/Commands/CreateDiagramContextMenuEntry.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2024 Christoph Wille for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Composition;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpyX.MermaidDiagrammer;
-
-using Microsoft.Win32;
-
-namespace ICSharpCode.ILSpy.TextView
-{
- [ExportContextMenuEntry(Header = nameof(Resources._CreateDiagram), Category = nameof(Resources.Save), Icon = "Images/Save")]
- [Shared]
- sealed class CreateDiagramContextMenuEntry(DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- var assembly = (context.SelectedTreeNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly;
- if (assembly == null)
- return;
-
- var selectedPath = SelectDestinationFolder();
- if (string.IsNullOrEmpty(selectedPath))
- return;
-
- dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- AvalonEditTextOutput output = new() {
- EnableHyperlinks = true
- };
- Stopwatch stopwatch = Stopwatch.StartNew();
- try
- {
- var command = new GenerateHtmlDiagrammer {
- Assembly = assembly.FileName,
- OutputFolder = selectedPath
- };
-
- command.Run();
- }
- catch (OperationCanceledException)
- {
- output.WriteLine();
- output.WriteLine(Resources.GenerationWasCancelled);
- throw;
- }
- stopwatch.Stop();
- output.WriteLine(Resources.GenerationCompleteInSeconds, stopwatch.Elapsed.TotalSeconds.ToString("F1"));
- output.WriteLine();
- output.WriteLine("Learn more: " + "https://github.com/icsharpcode/ILSpy/wiki/Diagramming#tips-for-using-the-html-diagrammer");
- output.WriteLine();
-
- var diagramHtml = Path.Combine(selectedPath, "index.html");
- output.AddButton(null, Resources.OpenExplorer, delegate { ShellHelper.OpenFolderAndSelectItem(diagramHtml); });
- output.WriteLine();
- return output;
- }, ct), Properties.Resources.CreatingDiagram).Then(dockWorkspace.ShowText).HandleExceptions();
-
- return;
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public bool IsVisible(TextViewContext context)
- {
- return context.SelectedTreeNodes?.Length == 1
- && context.SelectedTreeNodes?.FirstOrDefault() is AssemblyTreeNode tn
- && tn.LoadedAssembly.IsLoadedAsValidAssembly;
- }
-
- static string SelectDestinationFolder()
- {
- OpenFolderDialog dialog = new();
- dialog.Multiselect = false;
- dialog.Title = "Select target folder";
-
- if (dialog.ShowDialog() != true)
- {
- return null;
- }
-
- string selectedPath = Path.GetDirectoryName(dialog.FolderName);
- bool directoryNotEmpty;
- try
- {
- directoryNotEmpty = Directory.EnumerateFileSystemEntries(selectedPath).Any();
- }
- catch (Exception e) when (e is IOException || e is UnauthorizedAccessException || e is System.Security.SecurityException)
- {
- MessageBox.Show(
- "The directory cannot be accessed. Please ensure it exists and you have sufficient rights to access it.",
- "Target directory not accessible",
- MessageBoxButton.OK, MessageBoxImage.Error);
- return null;
- }
-
- return dialog.FolderName;
- }
- }
-}
diff --git a/ILSpy/Commands/DecompileAllCommand.cs b/ILSpy/Commands/DecompileAllCommand.cs
deleted file mode 100644
index 7a9bebf18..000000000
--- a/ILSpy/Commands/DecompileAllCommand.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#if DEBUG
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Composition;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading.Tasks;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpyX;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)]
- [Shared]
- sealed class DecompileAllCommand(AssemblyTreeModel assemblyTreeModel, DockWorkspace dockWorkspace) : SimpleCommand
- {
- public override bool CanExecute(object parameter)
- {
- return System.IO.Directory.Exists("c:\\temp\\decompiled");
- }
-
- public override void Execute(object parameter)
- {
- dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- Parallel.ForEach(
- Partitioner.Create(assemblyTreeModel.AssemblyList.GetAssemblies(), loadBalance: true),
- new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct },
- delegate (LoadedAssembly asm) {
- if (!asm.HasLoadError)
- {
- Stopwatch w = Stopwatch.StartNew();
- Exception exception = null;
- using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs"))
- {
- try
- {
- var options = dockWorkspace.ActiveTabPage.CreateDecompilationOptions();
- options.CancellationToken = ct;
- options.FullDecompilation = true;
- new CSharpLanguage().DecompileAssembly(asm, new PlainTextOutput(writer), options);
- }
- catch (Exception ex)
- {
- writer.WriteLine(ex.ToString());
- exception = ex;
- }
- }
- lock (output)
- {
- output.Write(asm.ShortName + " - " + w.Elapsed);
- if (exception != null)
- {
- output.Write(" - ");
- output.Write(exception.GetType().Name);
- }
- output.WriteLine();
- }
- }
- });
- return output;
- }, ct)).Then(dockWorkspace.ShowText).HandleExceptions();
- }
- }
-
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile100x), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)]
- [Shared]
- sealed class Decompile100TimesCommand(AssemblyTreeModel assemblyTreeModel, LanguageService languageService, DockWorkspace dockWorkspace) : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- const int numRuns = 100;
- var language = languageService.Language;
- var nodes = assemblyTreeModel.SelectedNodes.ToArray();
- var options = dockWorkspace.ActiveTabPage.CreateDecompilationOptions();
- dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- options.CancellationToken = ct;
- Stopwatch w = Stopwatch.StartNew();
- for (int i = 0; i < numRuns; ++i)
- {
- foreach (var node in nodes)
- {
- node.Decompile(language, new PlainTextOutput(), options);
- }
- }
- w.Stop();
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- double msPerRun = w.Elapsed.TotalMilliseconds / numRuns;
- output.Write($"Average time: {msPerRun.ToString("f1")}ms\n");
- return output;
- }, ct)).Then(output => dockWorkspace.ShowText(output)).HandleExceptions();
- }
- }
-}
-
-#endif
\ No newline at end of file
diff --git a/ILSpy/Commands/DecompileCommand.cs b/ILSpy/Commands/DecompileCommand.cs
deleted file mode 100644
index 6a909569e..000000000
--- a/ILSpy/Commands/DecompileCommand.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Linq;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-
-namespace ICSharpCode.ILSpy.Commands
-{
- [ExportContextMenuEntry(Header = nameof(Resources.Decompile), Order = 10)]
- [Shared]
- class DecompileCommand : IContextMenuEntry
- {
- public bool IsVisible(TextViewContext context)
- {
- if (context.SelectedTreeNodes == null)
- return context.Reference?.Reference is IEntity;
- return context.SelectedTreeNodes.Length == 1 && context.SelectedTreeNodes.All(n => n is IMemberTreeNode);
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- if (context.SelectedTreeNodes == null)
- return context.Reference?.Reference is IEntity;
- foreach (IMemberTreeNode node in context.SelectedTreeNodes)
- {
- if (!IsValidReference(node.Member))
- return false;
- }
-
- return true;
- }
-
- bool IsValidReference(object reference)
- {
- return reference is IEntity;
- }
-
- public void Execute(TextViewContext context)
- {
- IEntity selection = null;
- if (context.SelectedTreeNodes?[0] is IMemberTreeNode node)
- {
- selection = node.Member;
- }
- else if (context.Reference?.Reference is IEntity entity)
- {
- selection = entity;
- }
- if (selection != null)
- MessageBus.Send(this, new NavigateToReferenceEventArgs(selection));
- }
- }
-}
diff --git a/ILSpy/Commands/DecompileInNewViewCommand.cs b/ILSpy/Commands/DecompileInNewViewCommand.cs
deleted file mode 100644
index c6728be7e..000000000
--- a/ILSpy/Commands/DecompileInNewViewCommand.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Composition;
-using System.Linq;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-
-using TomsToolbox.Essentials;
-
-namespace ICSharpCode.ILSpy.Commands
-{
- [ExportContextMenuEntry(Header = nameof(Resources.DecompileToNewPanel), InputGestureText = "MMB", Icon = "images/Search", Category = nameof(Resources.Analyze), Order = 90)]
- [Shared]
- internal sealed class DecompileInNewViewCommand(AssemblyTreeModel assemblyTreeModel, DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public bool IsVisible(TextViewContext context)
- {
- return context.SelectedTreeNodes != null || context.Reference?.Reference is IEntity;
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- return GetNodes(context).Any();
- }
-
- public void Execute(TextViewContext context)
- {
- DecompileNodes(GetNodes(context).ToArray());
- }
-
- IEnumerable GetNodes(TextViewContext context)
- {
- if (context.SelectedTreeNodes != null)
- {
- if (context.TreeView.DataContext != assemblyTreeModel)
- {
- return context.SelectedTreeNodes.OfType().Select(FindTreeNode).ExceptNullItems();
- }
- else
- {
- return context.SelectedTreeNodes.OfType();
- }
- }
- else if (context.Reference?.Reference is IEntity entity)
- {
- if (assemblyTreeModel.FindTreeNode(entity) is { } node)
- {
- return new[] { node };
- }
- }
- return Array.Empty();
-
- ILSpyTreeNode FindTreeNode(IMemberTreeNode node)
- {
- if (node is ILSpyTreeNode ilspyNode)
- return ilspyNode;
- return assemblyTreeModel.FindTreeNode(node.Member);
- }
- }
-
- void DecompileNodes(ILSpyTreeNode[] nodes)
- {
- if (nodes.Length == 0)
- return;
-
- dockWorkspace.ActiveTabPage = dockWorkspace.AddTabPage();
-
- if (assemblyTreeModel.SelectedItems.SequenceEqual(nodes))
- assemblyTreeModel.DecompileSelectedNodes();
- else
- assemblyTreeModel.SelectNodes(nodes);
- }
- }
-}
diff --git a/ILSpy/Commands/DelegateCommand.cs b/ILSpy/Commands/DelegateCommand.cs
deleted file mode 100644
index 2c351730b..000000000
--- a/ILSpy/Commands/DelegateCommand.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Input;
-
-namespace ICSharpCode.ILSpy.Commands
-{
- public class DelegateCommand : ICommand
- {
- private readonly Action action;
- private readonly Func canExecute;
-
- public event EventHandler CanExecuteChanged {
- add { CommandManager.RequerySuggested += value; }
- remove { CommandManager.RequerySuggested -= value; }
- }
-
- public DelegateCommand(Action action)
- : this(action, () => true)
- {
- }
-
- public DelegateCommand(Action action, Func canExecute)
- {
- this.action = action;
- this.canExecute = canExecute;
- }
-
- public bool CanExecute(object parameter)
- {
- return canExecute();
- }
-
- public void Execute(object parameter)
- {
- action();
- }
- }
-
- public class DelegateCommand : ICommand
- {
- private readonly Action action;
- private readonly Func canExecute;
-
- public event EventHandler CanExecuteChanged {
- add { CommandManager.RequerySuggested += value; }
- remove { CommandManager.RequerySuggested -= value; }
- }
-
- public DelegateCommand(Action action)
- : this(action, _ => true)
- {
- }
-
- public DelegateCommand(Action action, Func canExecute)
- {
- this.action = action;
- this.canExecute = canExecute;
- }
-
- public bool CanExecute(object parameter)
- {
- return canExecute((T)parameter);
- }
-
- public void Execute(object parameter)
- {
- action((T)parameter);
- }
- }
-}
diff --git a/ILSpy/Commands/DisassembleAllCommand.cs b/ILSpy/Commands/DisassembleAllCommand.cs
deleted file mode 100644
index a43d00520..000000000
--- a/ILSpy/Commands/DisassembleAllCommand.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#if DEBUG
-
-using System;
-using System.Collections.Concurrent;
-using System.Composition;
-using System.Diagnostics;
-using System.Threading.Tasks;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.ViewModels;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDisassemble), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)]
- [Shared]
- sealed class DisassembleAllCommand(AssemblyTreeModel assemblyTreeModel, DockWorkspace dockWorkspace) : SimpleCommand
- {
- public override bool CanExecute(object parameter)
- {
- return System.IO.Directory.Exists("c:\\temp\\disassembled");
- }
-
- public override void Execute(object parameter)
- {
- dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- AvalonEditTextOutput output = new();
- Parallel.ForEach(
- Partitioner.Create(assemblyTreeModel.AssemblyList.GetAssemblies(), loadBalance: true),
- new() { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct },
- asm => {
- if (!asm.HasLoadError)
- {
- Stopwatch w = Stopwatch.StartNew();
- Exception exception = null;
- using (var writer = new System.IO.StreamWriter("c:\\temp\\disassembled\\" + asm.Text.Replace("(", "").Replace(")", "").Replace(' ', '_') + ".il"))
- {
- try
- {
- var options = dockWorkspace.ActiveTabPage.CreateDecompilationOptions();
- options.FullDecompilation = true;
- options.CancellationToken = ct;
- new ILLanguage(dockWorkspace).DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), options);
- }
- catch (Exception ex)
- {
- writer.WriteLine(ex.ToString());
- exception = ex;
- }
- }
- lock (output)
- {
- output.Write(asm.ShortName + " - " + w.Elapsed);
- if (exception != null)
- {
- output.Write(" - ");
- output.Write(exception.GetType().Name);
- }
- output.WriteLine();
- }
- }
- });
- return output;
- }, ct)).Then(dockWorkspace.ShowText).HandleExceptions();
- }
- }
-}
-
-#endif
\ No newline at end of file
diff --git a/ILSpy/Commands/ExitCommand.cs b/ILSpy/Commands/ExitCommand.cs
deleted file mode 100644
index b676c7ef9..000000000
--- a/ILSpy/Commands/ExitCommand.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-using System.Composition;
-
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.E_xit), MenuOrder = 99999, MenuCategory = nameof(Resources.Exit))]
- [Shared]
- sealed class ExitCommand(MainWindow mainWindow) : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- mainWindow.Close();
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Commands/ExportCommandAttribute.cs b/ILSpy/Commands/ExportCommandAttribute.cs
deleted file mode 100644
index 7b9709ff3..000000000
--- a/ILSpy/Commands/ExportCommandAttribute.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Composition;
-using System.Windows.Input;
-
-namespace ICSharpCode.ILSpy
-{
- #region Toolbar
- public interface IToolbarCommandMetadata
- {
- string ToolbarIcon { get; }
- string ToolTip { get; }
- string ToolbarCategory { get; }
- object Tag { get; }
- double ToolbarOrder { get; }
- }
-
- [MetadataAttribute]
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
- public class ExportToolbarCommandAttribute : ExportAttribute, IToolbarCommandMetadata
- {
- public ExportToolbarCommandAttribute()
- : base("ToolbarCommand", typeof(ICommand))
- {
- }
-
- public string ToolTip { get; set; }
- public string ToolbarIcon { get; set; }
- public string ToolbarCategory { get; set; }
- public double ToolbarOrder { get; set; }
- public object Tag { get; set; }
- }
- #endregion
-
- #region Main Menu
- public interface IMainMenuCommandMetadata
- {
- string MenuID { get; }
- string MenuIcon { get; }
- string Header { get; }
- string ParentMenuID { get; }
- string MenuCategory { get; }
- string InputGestureText { get; }
- bool IsEnabled { get; }
- double MenuOrder { get; }
- }
-
- [MetadataAttribute]
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
- public class ExportMainMenuCommandAttribute : ExportAttribute, IMainMenuCommandMetadata
- {
- public ExportMainMenuCommandAttribute()
- : base("MainMenuCommand", typeof(ICommand))
- {
- }
- ///
- /// Gets/Sets the ID of this menu item. Menu entries are not required to have an ID,
- /// however, setting it allows to declare nested menu structures.
- /// The built-in menus have the IDs "_File", "_View", "_Window" and "_Help".
- /// Plugin authors are advised to use GUIDs as identifiers to prevent conflicts.
- ///
- /// NOTE: Defining cycles (for example by accidentally setting equal to )
- /// will lead to a stack-overflow and crash of ILSpy at startup.
- ///
- public string MenuID { get; set; }
- public string MenuIcon { get; set; }
- public string Header { get; set; }
- ///
- /// Gets/Sets the parent of this menu item. All menu items sharing the same parent will be displayed as sub-menu items.
- /// If this property is set to , the menu item is displayed in the top-level menu.
- /// The built-in menus have the IDs "_File", "_View", "_Window" and "_Help".
- ///
- /// NOTE: Defining cycles (for example by accidentally setting equal to )
- /// will lead to a stack-overflow and crash of ILSpy at startup.
- ///
- public string ParentMenuID { get; set; }
- public string MenuCategory { get; set; }
- public string InputGestureText { get; set; }
- public bool IsEnabled { get; set; } = true;
- public double MenuOrder { get; set; }
- }
- #endregion
-
- #region Tool Panes
-
- [MetadataAttribute]
- [AttributeUsage(AttributeTargets.Class)]
- public class ExportToolPaneAttribute : ExportAttribute
- {
- public ExportToolPaneAttribute()
- : base("ToolPane", typeof(ViewModels.ToolPaneModel))
- {
- }
- }
- #endregion
-}
diff --git a/ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs b/ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs
deleted file mode 100644
index 85a1be6f2..000000000
--- a/ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright (c) 2021 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Composition;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
-using ICSharpCode.Decompiler.Util;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.TreeView;
-
-using Microsoft.Win32;
-
-using static ICSharpCode.ILSpyX.LoadedPackage;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportContextMenuEntry(Header = nameof(Resources.ExtractPackageEntry), Category = nameof(Resources.Save), Icon = "Images/Save")]
- [Shared]
- sealed class ExtractPackageEntryContextMenuEntry(DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- var selectedNodes = Array.FindAll(context.SelectedTreeNodes, IsBundleItem);
- // Get root assembly to infer the initial directory for the save dialog.
- var bundleNode = selectedNodes.FirstOrDefault()?.Ancestors().OfType()
- .FirstOrDefault(asm => asm.PackageEntry == null);
- if (bundleNode == null)
- return;
- if (selectedNodes is [AssemblyTreeNode { PackageEntry: { } assembly }])
- {
- SaveFileDialog dlg = new SaveFileDialog();
- dlg.FileName = Path.GetFileName(WholeProjectDecompiler.SanitizeFileName(assembly.Name));
- dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd" + Resources.AllFiles;
- dlg.InitialDirectory = Path.GetDirectoryName(bundleNode.LoadedAssembly.FileName);
- if (dlg.ShowDialog() == true)
- Save(dockWorkspace, selectedNodes, dlg.FileName, true);
- }
- else if (selectedNodes is [ResourceTreeNode { Resource: { } resource }])
- {
- SaveFileDialog dlg = new SaveFileDialog();
- dlg.FileName = Path.GetFileName(WholeProjectDecompiler.SanitizeFileName(resource.Name));
- dlg.Filter = Resources.AllFiles[1..];
- dlg.InitialDirectory = Path.GetDirectoryName(bundleNode.LoadedAssembly.FileName);
- if (dlg.ShowDialog() == true)
- Save(dockWorkspace, selectedNodes, dlg.FileName, true);
- }
- else
- {
- OpenFolderDialog dlg = new OpenFolderDialog();
- dlg.InitialDirectory = Path.GetDirectoryName(bundleNode.LoadedAssembly.FileName);
- if (dlg.ShowDialog() != true)
- return;
-
- string folderName = dlg.FolderName;
- if (Directory.EnumerateFileSystemEntries(folderName).Any())
- {
- var result = MessageBox.Show(
- Resources.AssemblySaveCodeDirectoryNotEmpty,
- Resources.AssemblySaveCodeDirectoryNotEmptyTitle,
- MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
- if (result == MessageBoxResult.No)
- return;
- }
-
- Save(dockWorkspace, selectedNodes, folderName, false);
- }
- }
-
- internal static void Save(DockWorkspace dockWorkspace, ICollection nodes, string path, bool isFile)
- {
- dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- Stopwatch stopwatch = Stopwatch.StartNew();
- Dictionary fileNameCounts = new Dictionary(Platform.FileNameComparer);
- foreach (var (entry, fileName) in CollectAllFiles(nodes))
- {
- string actualFileName = WholeProjectDecompiler.SanitizeFileName(fileName);
- while (fileNameCounts.TryGetValue(actualFileName, out int index))
- {
- index++;
- fileNameCounts[actualFileName] = index;
- actualFileName = Path.ChangeExtension(actualFileName, index + Path.GetExtension(actualFileName));
- }
- if (!fileNameCounts.ContainsKey(actualFileName))
- {
- fileNameCounts[actualFileName] = 1;
- }
- SaveEntry(output, entry, Path.Combine(path, actualFileName));
- }
- stopwatch.Stop();
- output.WriteLine(Resources.GenerationCompleteInSeconds, stopwatch.Elapsed.TotalSeconds.ToString("F1"));
- output.WriteLine();
- // If we have written files, open explorer and select them grouped by folder; otherwise fall back to opening containing folder.
- if (isFile && File.Exists(path))
- output.AddButton(null, Resources.OpenExplorer, delegate { ShellHelper.OpenFolderAndSelectItem(path); });
- else
- output.AddButton(null, Resources.OpenExplorer, delegate { ShellHelper.OpenFolder(path); });
- output.WriteLine();
- return output;
- }, ct)).Then(dockWorkspace.ShowText).HandleExceptions();
-
- static IEnumerable<(PackageEntry Entry, string TargetFileName)> CollectAllFiles(ICollection nodes)
- {
- foreach (var node in nodes)
- {
- if (node is AssemblyTreeNode { PackageEntry: { } assembly })
- {
- yield return (assembly, Path.GetFileName(assembly.FullName));
- }
- else if (node is ResourceTreeNode { Resource: PackageEntry { } resource })
- {
- yield return (resource, Path.GetFileName(resource.FullName));
- }
- else if (node is AssemblyTreeNode { PackageKind: not null } asm)
- {
- var package = asm.LoadedAssembly.GetLoadResultAsync().GetAwaiter().GetResult().Package;
- foreach (var entry in package.Entries)
- {
- yield return (entry, entry.FullName);
- }
- }
- else if (node is PackageFolderTreeNode folder)
- {
- int prefixLength = 0;
- PackageFolder current = folder.Folder;
- if (nodes.Count > 1)
- current = current.Parent;
- while (current != null)
- {
- prefixLength += current.Name.Length + 1;
- current = current.Parent;
- }
- if (prefixLength > 0)
- prefixLength--;
- foreach (var item in TreeTraversal.PreOrder(folder.Folder, f => f.Folders).SelectMany(f => f.Entries))
- {
- yield return (item, item.FullName.Substring(prefixLength));
- }
- }
- }
- }
- }
-
- static void SaveEntry(ITextOutput output, PackageEntry entry, string targetFileName)
- {
- output.Write(entry.Name + ": ");
- using Stream stream = entry.TryOpenStream();
- if (stream == null)
- {
- output.WriteLine("Could not open stream!");
- return;
- }
-
- Directory.CreateDirectory(Path.GetDirectoryName(targetFileName));
-
- stream.Position = 0;
- using FileStream fileStream = new FileStream(targetFileName, FileMode.OpenOrCreate);
- stream.CopyTo(fileStream);
- output.WriteLine("Written to " + targetFileName);
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public bool IsVisible(TextViewContext context) => context.SelectedTreeNodes?.Any(IsBundleItem) == true;
-
- static bool IsBundleItem(SharpTreeNode node)
- {
- if (node is AssemblyTreeNode { PackageEntry: { } } or PackageFolderTreeNode)
- return true;
- if (node is ResourceTreeNode { Resource: PackageEntry { } resource } && resource.PackageQualifiedFileName.StartsWith("bundle://"))
- return true;
- return false;
- }
- }
-
- [ExportContextMenuEntry(Header = nameof(Resources.ExtractAllPackageEntries), Category = nameof(Resources.Save), Icon = "Images/Save")]
- [Shared]
- sealed class ExtractAllPackageEntriesContextMenuEntry(DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- if (context.SelectedTreeNodes is not [AssemblyTreeNode { PackageEntry: null } asm])
- return;
- OpenFolderDialog dlg = new OpenFolderDialog();
- dlg.InitialDirectory = Path.GetDirectoryName(asm.LoadedAssembly.FileName);
- if (dlg.ShowDialog() != true)
- return;
-
- string folderName = dlg.FolderName;
- if (Directory.EnumerateFileSystemEntries(folderName).Any())
- {
- var result = MessageBox.Show(
- Resources.AssemblySaveCodeDirectoryNotEmpty,
- Resources.AssemblySaveCodeDirectoryNotEmptyTitle,
- MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
- if (result == MessageBoxResult.No)
- return;
- }
-
- ExtractPackageEntryContextMenuEntry.Save(dockWorkspace, [asm], folderName, false);
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public bool IsVisible(TextViewContext context)
- {
- return context.SelectedTreeNodes is [AssemblyTreeNode { PackageEntry: null, PackageKind: PackageKind.Bundle }];
- }
- }
-}
diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs
deleted file mode 100644
index 41b7018d4..000000000
--- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright (c) 2018 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Composition;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.CSharp;
-using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
-using ICSharpCode.Decompiler.DebugInfo;
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpyX;
-
-using Microsoft.Win32;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportContextMenuEntry(Header = nameof(Resources.GeneratePortable))]
- [Shared]
- class GeneratePdbContextMenuEntry(LanguageService languageService, DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- var selectedNodes = context.SelectedTreeNodes?.OfType().ToArray();
- if (selectedNodes == null || selectedNodes.Length == 0)
- return;
-
- GeneratePdbForAssemblies(selectedNodes.Select(n => n.LoadedAssembly), languageService, dockWorkspace);
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public bool IsVisible(TextViewContext context)
- {
- var selectedNodes = context.SelectedTreeNodes;
- return selectedNodes?.Any() == true
- && selectedNodes.All(n => n is AssemblyTreeNode asm && asm.LoadedAssembly.IsLoadedAsValidAssembly);
- }
-
- internal static void GeneratePdbForAssemblies(IEnumerable assemblies, LanguageService languageService, DockWorkspace dockWorkspace)
- {
- var assemblyArray = assemblies?.Where(a => a != null).ToArray() ?? [];
- if (assemblyArray == null || assemblyArray.Length == 0)
- return;
-
- // Ensure at least one assembly supports PDB generation
- var supported = new Dictionary();
- var unsupported = new List();
- foreach (var a in assemblyArray)
- {
- try
- {
- var file = a.GetMetadataFileOrNull() as PEFile;
- if (PortablePdbWriter.HasCodeViewDebugDirectoryEntry(file))
- supported.Add(a, file);
- else
- unsupported.Add(a);
- }
- catch
- {
- unsupported.Add(a);
- }
- }
- if (supported.Count == 0)
- {
- // none can be generated
- string msg = string.Format(Resources.CannotCreatePDBFile, ":" + Environment.NewLine +
- string.Join(Environment.NewLine, unsupported.Select(u => Path.GetFileName(u.FileName)))
- + Environment.NewLine);
- MessageBox.Show(msg);
- return;
- }
-
- // Ask for target folder
- var dlg = new OpenFolderDialog();
- dlg.Title = Resources.SelectPDBOutputFolder;
- if (dlg.ShowDialog() != true || string.IsNullOrWhiteSpace(dlg.FolderName))
- return;
-
- string targetFolder = dlg.FolderName;
- DecompilationOptions options = dockWorkspace.ActiveTabPage.CreateDecompilationOptions();
-
- dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- Stopwatch totalWatch = Stopwatch.StartNew();
- options.CancellationToken = ct;
-
- int total = assemblyArray.Length;
- int processed = 0;
- foreach (var assembly in assemblyArray)
- {
- // only process supported assemblies
- if (!supported.TryGetValue(assembly, out var file))
- {
- output.WriteLine(string.Format(Resources.CannotCreatePDBFile, Path.GetFileName(assembly.FileName)));
- processed++;
- if (options.Progress != null)
- {
- options.Progress.Report(new DecompilationProgress {
- Title = string.Format(Resources.GeneratingPortablePDB, Path.GetFileName(assembly.FileName)),
- TotalUnits = total,
- UnitsCompleted = processed
- });
- }
- continue;
- }
-
- string fileName = Path.Combine(targetFolder, WholeProjectDecompiler.CleanUpFileName(assembly.ShortName, ".pdb"));
-
- try
- {
- using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
- {
- var decompiler = new CSharpDecompiler(file, assembly.GetAssemblyResolver(options.DecompilerSettings.AutoLoadAssemblyReferences), options.DecompilerSettings);
- decompiler.CancellationToken = ct;
- PortablePdbWriter.WritePdb(file, decompiler, options.DecompilerSettings, stream, progress: options.Progress, currentProgressTitle: string.Format(Resources.GeneratingPortablePDB, Path.GetFileName(assembly.FileName)));
- }
- output.WriteLine(string.Format(Resources.GeneratedPDBFile, fileName));
- }
- catch (OperationCanceledException)
- {
- output.WriteLine();
- output.WriteLine(Resources.GenerationWasCancelled);
- throw;
- }
- catch (Exception ex)
- {
- output.WriteLine(string.Format(Resources.GenerationFailedForAssembly, assembly.FileName, ex.Message));
- }
- processed++;
- if (options.Progress != null)
- {
- options.Progress.Report(new DecompilationProgress {
- Title = string.Format(Resources.GeneratingPortablePDB, Path.GetFileName(assembly.FileName)),
- TotalUnits = total,
- UnitsCompleted = processed
- });
- }
- }
-
- totalWatch.Stop();
- output.WriteLine();
- output.WriteLine(Resources.GenerationCompleteInSeconds, totalWatch.Elapsed.TotalSeconds.ToString("F1"));
- output.WriteLine();
- // Select all generated pdb files in explorer
- var generatedFiles = assemblyArray
- .Select(a => Path.Combine(targetFolder, WholeProjectDecompiler.CleanUpFileName(a.ShortName, ".pdb")))
- .Where(File.Exists)
- .ToList();
- if (generatedFiles.Any())
- {
- output.AddButton(null, Resources.OpenExplorer, delegate { ShellHelper.OpenFolderAndSelectItems(generatedFiles); });
- }
- else
- {
- output.AddButton(null, Resources.OpenExplorer, delegate { ShellHelper.OpenFolder(targetFolder); });
- }
- output.WriteLine();
- return output;
- }, ct)).Then(dockWorkspace.ShowText).HandleExceptions();
- }
- }
-
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = nameof(Resources.Save))]
- [Shared]
- class GeneratePdbMainMenuEntry(AssemblyTreeModel assemblyTreeModel, LanguageService languageService, DockWorkspace dockWorkspace) : SimpleCommand
- {
- public override bool CanExecute(object parameter)
- {
- return assemblyTreeModel.SelectedNodes?.Any() == true
- && assemblyTreeModel.SelectedNodes?.All(n => n is AssemblyTreeNode tn && !tn.LoadedAssembly.HasLoadError) == true;
- }
-
- public override void Execute(object parameter)
- {
- var selectedNodes = assemblyTreeModel.SelectedNodes?.OfType().ToArray();
- if (selectedNodes == null || selectedNodes.Length == 0)
- return;
-
- GeneratePdbContextMenuEntry.GeneratePdbForAssemblies(selectedNodes.Select(n => n.LoadedAssembly), languageService, dockWorkspace);
- }
- }
-}
diff --git a/ILSpy/Commands/IProtocolHandler.cs b/ILSpy/Commands/IProtocolHandler.cs
deleted file mode 100644
index b9e675bfc..000000000
--- a/ILSpy/Commands/IProtocolHandler.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2018 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Reflection.Metadata;
-
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.ILSpy.TreeNodes;
-
-namespace ICSharpCode.ILSpy
-{
- public interface IProtocolHandler
- {
- ILSpyTreeNode Resolve(string protocol, MetadataFile module, Handle handle, out bool newTabPage);
- }
-}
diff --git a/ILSpy/Commands/ManageAssemblyListsCommand.cs b/ILSpy/Commands/ManageAssemblyListsCommand.cs
deleted file mode 100644
index 8e66c9a9d..000000000
--- a/ILSpy/Commands/ManageAssemblyListsCommand.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Windows;
-using System.Windows.Data;
-
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ManageAssembly_Lists), MenuIcon = "Images/AssemblyList", MenuCategory = nameof(Resources.Open), MenuOrder = 1.7)]
- [Shared]
- sealed class ManageAssemblyListsCommand(SettingsService settingsService) : SimpleCommand, IProvideParameterBinding
- {
- public override void Execute(object parameter)
- {
- ManageAssemblyListsDialog dlg = new(settingsService) {
- Owner = parameter as Window
- };
-
- dlg.ShowDialog();
- }
-
- public Binding ParameterBinding => new() {
- RelativeSource = new(RelativeSourceMode.FindAncestor) {
- AncestorType = typeof(Window)
- }
- };
- }
-}
diff --git a/ILSpy/Commands/OpenCommand.cs b/ILSpy/Commands/OpenCommand.cs
deleted file mode 100644
index 2ea160889..000000000
--- a/ILSpy/Commands/OpenCommand.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Windows.Input;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-
-using Microsoft.Win32;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportToolbarCommand(ToolTip = nameof(Resources.Open), ToolbarIcon = "Images/Open", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 0)]
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._Open), MenuIcon = "Images/Open", MenuCategory = nameof(Resources.Open), MenuOrder = 0)]
- [Shared]
- sealed class OpenCommand : CommandWrapper
- {
- private readonly AssemblyTreeModel assemblyTreeModel;
-
- public OpenCommand(AssemblyTreeModel assemblyTreeModel)
- : base(ApplicationCommands.Open)
- {
- this.assemblyTreeModel = assemblyTreeModel;
- }
-
- protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
- {
- e.Handled = true;
- OpenFileDialog dlg = new OpenFileDialog {
- Filter = ".NET assemblies|*.dll;*.exe;*.winmd;*.wasm|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*",
- Multiselect = true,
- RestoreDirectory = true
- };
-
- if (dlg.ShowDialog() == true)
- {
- assemblyTreeModel.OpenFiles(dlg.FileNames);
- }
- }
- }
-}
diff --git a/ILSpy/Commands/OpenFromGacCommand.cs b/ILSpy/Commands/OpenFromGacCommand.cs
deleted file mode 100644
index b66e1c644..000000000
--- a/ILSpy/Commands/OpenFromGacCommand.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-
-using ICSharpCode.ILSpy.AppEnv;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.OpenFrom_GAC), MenuIcon = "Images/AssemblyListGAC", MenuCategory = nameof(Resources.Open), MenuOrder = 1)]
- [Shared]
- sealed class OpenFromGacCommand(AssemblyTreeModel assemblyTreeModel, MainWindow mainWindow) : SimpleCommand
- {
- public override bool CanExecute(object parameter)
- {
- return AppEnvironment.IsWindows;
- }
-
- public override void Execute(object parameter)
- {
- OpenFromGacDialog dlg = new() {
- Owner = mainWindow
- };
-
- if (dlg.ShowDialog() == true)
- {
- assemblyTreeModel.OpenFiles(dlg.SelectedFileNames);
- }
- }
- }
-}
diff --git a/ILSpy/Commands/Pdb2XmlCommand.cs b/ILSpy/Commands/Pdb2XmlCommand.cs
deleted file mode 100644
index fb554c321..000000000
--- a/ILSpy/Commands/Pdb2XmlCommand.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-#if DEBUG && WINDOWS
-
-using System.Collections.Generic;
-using System.Composition;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-
-using ICSharpCode.AvalonEdit.Highlighting;
-using ICSharpCode.Decompiler;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.TreeNodes;
-
-using Microsoft.DiaSymReader.Tools;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDumpPDBAsXML), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)]
- [Shared]
- sealed class Pdb2XmlCommand(AssemblyTreeModel assemblyTreeModel, DockWorkspace dockWorkspace) : SimpleCommand
- {
- public override bool CanExecute(object parameter)
- {
- var selectedNodes = assemblyTreeModel.SelectedNodes;
- return selectedNodes?.Any() == true
- && selectedNodes.All(n => n is AssemblyTreeNode asm && !asm.LoadedAssembly.HasLoadError);
- }
-
- public override void Execute(object parameter)
- {
- Execute(assemblyTreeModel.SelectedNodes.OfType(), dockWorkspace);
- }
-
- internal static void Execute(IEnumerable nodes, DockWorkspace dockWorkspace)
- {
- var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml");
- var options = PdbToXmlOptions.IncludeEmbeddedSources | PdbToXmlOptions.IncludeMethodSpans | PdbToXmlOptions.IncludeTokens;
- dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- var writer = new TextOutputWriter(output);
- foreach (var node in nodes)
- {
- string pdbFileName = Path.ChangeExtension(node.LoadedAssembly.FileName, ".pdb");
- if (!File.Exists(pdbFileName))
- continue;
- using (var pdbStream = File.OpenRead(pdbFileName))
- using (var peStream = File.OpenRead(node.LoadedAssembly.FileName))
- PdbToXmlConverter.ToXml(writer, pdbStream, peStream, options);
- }
- return output;
- }, ct)).Then(output => dockWorkspace.ShowNodes(output, null, highlighting)).HandleExceptions();
- }
- }
-
- [ExportContextMenuEntry(Header = nameof(Resources.DEBUGDumpPDBAsXML))]
- [Shared]
- class Pdb2XmlCommandContextMenuEntry(DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- Pdb2XmlCommand.Execute(context.SelectedTreeNodes.OfType(), dockWorkspace);
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public bool IsVisible(TextViewContext context)
- {
- var selectedNodes = context.SelectedTreeNodes;
- return selectedNodes?.Any() == true
- && selectedNodes.All(n => n is AssemblyTreeNode asm && asm.LoadedAssembly.IsLoadedAsValidAssembly);
- }
- }
-
-}
-
-#endif
diff --git a/ILSpy/Commands/RefreshCommand.cs b/ILSpy/Commands/RefreshCommand.cs
deleted file mode 100644
index d82ac11ab..000000000
--- a/ILSpy/Commands/RefreshCommand.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Windows.Input;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportToolbarCommand(ToolTip = nameof(Resources.RefreshCommand_ReloadAssemblies), ToolbarIcon = "Images/Refresh", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 2)]
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._Reload), MenuIcon = "Images/Refresh", MenuCategory = nameof(Resources.Open), MenuOrder = 2)]
- [Shared]
- sealed class RefreshCommand : CommandWrapper
- {
- private readonly AssemblyTreeModel assemblyTreeModel;
-
- public RefreshCommand(AssemblyTreeModel assemblyTreeModel)
- : base(NavigationCommands.Refresh)
- {
- this.assemblyTreeModel = assemblyTreeModel;
- }
-
- protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
- {
- assemblyTreeModel.Refresh();
- }
- }
-}
diff --git a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
deleted file mode 100644
index 00531a5b9..000000000
--- a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2018 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Linq;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._RemoveAssembliesWithLoadErrors), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)]
- [Shared]
- class RemoveAssembliesWithLoadErrors(AssemblyTreeModel assemblyTreeModel) : SimpleCommand
- {
- public override bool CanExecute(object parameter)
- {
- return assemblyTreeModel.AssemblyList.GetAssemblies().Any(l => l.HasLoadError);
- }
-
- public override void Execute(object parameter)
- {
- foreach (var assembly in assemblyTreeModel.AssemblyList.GetAssemblies())
- {
- if (!assembly.HasLoadError)
- continue;
- var node = assemblyTreeModel.FindAssemblyNode(assembly);
- if (node != null && node.CanDelete())
- node.Delete();
- }
- }
- }
-
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ClearAssemblyList), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)]
- [Shared]
- class ClearAssemblyList : SimpleCommand
- {
- private readonly AssemblyTreeModel assemblyTreeModel;
-
- public ClearAssemblyList(AssemblyTreeModel assemblyTreeModel)
- {
- this.assemblyTreeModel = assemblyTreeModel;
- }
-
- public override bool CanExecute(object parameter)
- {
- return assemblyTreeModel.AssemblyList.Count > 0;
- }
-
- public override void Execute(object parameter)
- {
- assemblyTreeModel.AssemblyList.Clear();
- }
- }
-}
diff --git a/ILSpy/Commands/SaveCodeContextMenuEntry.cs b/ILSpy/Commands/SaveCodeContextMenuEntry.cs
deleted file mode 100644
index 75a35b208..000000000
--- a/ILSpy/Commands/SaveCodeContextMenuEntry.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Composition;
-using System.IO;
-using System.Linq;
-using System.Windows;
-
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpyX.TreeView;
-
-using Microsoft.Win32;
-
-namespace ICSharpCode.ILSpy.TextView
-{
- [ExportContextMenuEntry(Header = nameof(Resources._SaveCode), Category = nameof(Resources.Save), Icon = "Images/Save")]
- [Shared]
- sealed class SaveCodeContextMenuEntry(LanguageService languageService, DockWorkspace dockWorkspace) : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- Execute(context.SelectedTreeNodes, languageService, dockWorkspace);
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public bool IsVisible(TextViewContext context)
- {
- return CanExecute(context.SelectedTreeNodes);
- }
-
- public static bool CanExecute(IReadOnlyList selectedNodes)
- {
- if (selectedNodes == null || selectedNodes.Any(n => !(n is ILSpyTreeNode)))
- return false;
- return selectedNodes.Count == 1
- || (selectedNodes.Count > 1 && (selectedNodes.All(n => n is AssemblyTreeNode) || selectedNodes.All(n => n is IMemberTreeNode)));
- }
-
- public static void Execute(IReadOnlyList selectedNodes, LanguageService languageService, DockWorkspace dockWorkspace)
- {
- var currentLanguage = languageService.Language;
- var tabPage = dockWorkspace.ActiveTabPage;
- tabPage.ShowTextView(textView => {
- if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection)
- {
- // if there's only one treenode selected
- // we will invoke the custom Save logic
- if (singleSelection.Save(tabPage))
- return;
- }
- else if (selectedNodes.Count > 1 && selectedNodes.All(n => n is AssemblyTreeNode { LoadedAssembly.IsLoadedAsValidAssembly: true }))
- {
- var selectedPath = SelectSolutionFile();
-
- if (!string.IsNullOrEmpty(selectedPath))
- {
- var assemblies = selectedNodes.OfType()
- .Select(n => n.LoadedAssembly)
- .Where(a => a.IsLoadedAsValidAssembly).ToList();
- SolutionWriter.CreateSolution(tabPage, textView, selectedPath, currentLanguage, assemblies);
- }
- return;
- }
-
- // Fallback: if nobody was able to handle the request, use default behavior.
- // try to save all nodes to disk.
- var options = dockWorkspace.ActiveTabPage.CreateDecompilationOptions();
- options.FullDecompilation = true;
- textView.SaveToDisk(currentLanguage, selectedNodes.OfType(), options);
- });
- }
-
- ///
- /// Shows a File Selection dialog where the user can select the target file for the solution.
- ///
- /// The initial path to show in the dialog. If not specified, the 'Documents' directory
- /// will be used.
- ///
- /// The full path of the selected target file, or null if the user canceled.
- static string SelectSolutionFile()
- {
- SaveFileDialog dlg = new SaveFileDialog();
- dlg.FileName = "Solution.sln";
- dlg.Filter = Resources.VisualStudioSolutionFileSlnAllFiles;
-
- if (dlg.ShowDialog() != true)
- {
- return null;
- }
-
- string selectedPath = Path.GetDirectoryName(dlg.FileName);
- bool directoryNotEmpty;
- try
- {
- directoryNotEmpty = Directory.EnumerateFileSystemEntries(selectedPath).Any();
- }
- catch (Exception e) when (e is IOException || e is UnauthorizedAccessException || e is System.Security.SecurityException)
- {
- MessageBox.Show(
- "The directory cannot be accessed. Please ensure it exists and you have sufficient rights to access it.",
- "Solution directory not accessible",
- MessageBoxButton.OK, MessageBoxImage.Error);
- return null;
- }
-
- if (directoryNotEmpty)
- {
- var result = MessageBox.Show(
- Resources.AssemblySaveCodeDirectoryNotEmpty,
- Resources.AssemblySaveCodeDirectoryNotEmptyTitle,
- MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
- if (result == MessageBoxResult.No)
- return null; // -> abort
- }
-
- return dlg.FileName;
- }
- }
-}
diff --git a/ILSpy/Commands/SaveCommand.cs b/ILSpy/Commands/SaveCommand.cs
deleted file mode 100644
index ae5ca6505..000000000
--- a/ILSpy/Commands/SaveCommand.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.Linq;
-using System.Windows.Input;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TextView;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._SaveCode), MenuIcon = "Images/Save", MenuCategory = nameof(Resources.Save), MenuOrder = 0)]
- [Shared]
- sealed class SaveCommand(AssemblyTreeModel assemblyTreeModel, LanguageService languageService, DockWorkspace dockWorkspace) : CommandWrapper(ApplicationCommands.Save)
- {
- protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- e.Handled = true;
- e.CanExecute = SaveCodeContextMenuEntry.CanExecute(assemblyTreeModel.SelectedNodes.ToList());
- }
-
- protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
- {
- SaveCodeContextMenuEntry.Execute(assemblyTreeModel.SelectedNodes.ToList(), languageService, dockWorkspace);
- }
- }
-}
diff --git a/ILSpy/Commands/ScopeSearchToAssembly.cs b/ILSpy/Commands/ScopeSearchToAssembly.cs
deleted file mode 100644
index e839ebeb3..000000000
--- a/ILSpy/Commands/ScopeSearchToAssembly.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2021 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-#nullable enable
-
-using System;
-using System.Composition;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.AppEnv;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.Search;
-using ICSharpCode.ILSpy.TreeNodes;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportContextMenuEntry(Header = nameof(Resources.ScopeSearchToThisAssembly), Category = nameof(Resources.Analyze), Order = 9999)]
- [Shared]
- public class ScopeSearchToAssembly : IContextMenuEntry
- {
- private readonly SearchPaneModel searchPane;
-
- public ScopeSearchToAssembly(SearchPaneModel searchPane)
- {
- this.searchPane = searchPane;
- }
-
- public void Execute(TextViewContext context)
- {
- // asmName cannot be null here, because Execute is only called if IsEnabled/IsVisible return true.
- string asmName = GetAssembly(context)!;
- string searchTerm = searchPane.SearchTerm;
- string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
- bool replaced = false;
- for (int i = 0; i < args.Length; i++)
- {
- if (args[i].StartsWith("inassembly:", StringComparison.OrdinalIgnoreCase))
- {
- args[i] = "inassembly:" + asmName;
- replaced = true;
- break;
- }
- }
- if (!replaced)
- {
- searchTerm += " inassembly:" + asmName;
- }
- else
- {
- searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
- }
- searchPane.SearchTerm = searchTerm;
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- return GetAssembly(context) != null;
- }
-
- public bool IsVisible(TextViewContext context)
- {
- return GetAssembly(context) != null;
- }
-
- string? GetAssembly(TextViewContext context)
- {
- if (context.Reference?.Reference is IEntity entity)
- return entity.ParentModule?.AssemblyName;
- if (context.SelectedTreeNodes?.Length != 1)
- return null;
- switch (context.SelectedTreeNodes[0])
- {
- case AssemblyTreeNode tn:
- return tn.LoadedAssembly.ShortName;
- case IMemberTreeNode member:
- return member.Member?.ParentModule?.AssemblyName;
- default:
- return null;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Commands/ScopeSearchToNamespace.cs b/ILSpy/Commands/ScopeSearchToNamespace.cs
deleted file mode 100644
index ae0914440..000000000
--- a/ILSpy/Commands/ScopeSearchToNamespace.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2021 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-using System;
-using System.Composition;
-
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.ILSpy.AppEnv;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.Search;
-using ICSharpCode.ILSpy.TreeNodes;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportContextMenuEntry(Header = nameof(Resources.ScopeSearchToThisNamespace), Category = nameof(Resources.Analyze), Order = 9999)]
- [Shared]
- public class ScopeSearchToNamespace : IContextMenuEntry
- {
- private readonly SearchPaneModel searchPane;
-
- public ScopeSearchToNamespace(SearchPaneModel searchPane)
- {
- this.searchPane = searchPane;
- }
-
- public void Execute(TextViewContext context)
- {
- string ns = GetNamespace(context);
- string searchTerm = searchPane.SearchTerm;
- string[] args = CommandLineTools.CommandLineToArgumentArray(searchTerm);
- bool replaced = false;
- for (int i = 0; i < args.Length; i++)
- {
- if (args[i].StartsWith("innamespace:", StringComparison.OrdinalIgnoreCase))
- {
- args[i] = "innamespace:" + ns;
- replaced = true;
- break;
- }
- }
- if (!replaced)
- {
- searchTerm += " innamespace:" + ns;
- }
- else
- {
- searchTerm = CommandLineTools.ArgumentArrayToCommandLine(args);
- }
-
- searchPane.SearchTerm = searchTerm;
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- return GetNamespace(context) != null;
- }
-
- public bool IsVisible(TextViewContext context)
- {
- return GetNamespace(context) != null;
- }
-
- string GetNamespace(TextViewContext context)
- {
- if (context.Reference?.Reference is IEntity entity)
- return entity.Namespace;
- if (context.SelectedTreeNodes?.Length != 1)
- return null;
- switch (context.SelectedTreeNodes[0])
- {
- case NamespaceTreeNode tn:
- return tn.Name;
- case IMemberTreeNode member:
- return member.Member.Namespace;
- default:
- return null;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Commands/SearchMsdnContextMenuEntry.cs b/ILSpy/Commands/SearchMsdnContextMenuEntry.cs
deleted file mode 100644
index b1dce4c22..000000000
--- a/ILSpy/Commands/SearchMsdnContextMenuEntry.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Linq;
-
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-namespace ICSharpCode.ILSpy
-{
- using System.Composition;
-
- using ICSharpCode.Decompiler.TypeSystem;
-
- [ExportContextMenuEntry(Header = nameof(Resources.SearchMSDN), Icon = "images/SearchMsdn", Order = 9999)]
- [Shared]
- internal sealed class SearchMsdnContextMenuEntry : IContextMenuEntry
- {
- private static string msdnAddress = "https://docs.microsoft.com/dotnet/api/{0}";
-
- public bool IsVisible(TextViewContext context)
- {
- if (context.SelectedTreeNodes == null)
- return false;
-
- return context.SelectedTreeNodes.All(
- n => n is NamespaceTreeNode
- || n is TypeTreeNode
- || n is EventTreeNode
- || n is FieldTreeNode
- || n is PropertyTreeNode
- || n is MethodTreeNode);
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- if (context.SelectedTreeNodes == null)
- return false;
-
- foreach (var node in context.SelectedTreeNodes)
- {
- if (node is TypeTreeNode typeNode && !typeNode.IsPublicAPI)
- return false;
-
- if (node is EventTreeNode eventNode && (!eventNode.IsPublicAPI || !IsAccessible(eventNode.EventDefinition)))
- return false;
-
- if (node is FieldTreeNode fieldNode && (!fieldNode.IsPublicAPI || !IsAccessible(fieldNode.FieldDefinition) || IsDelegateOrEnumMember(fieldNode.FieldDefinition)))
- return false;
-
- if (node is PropertyTreeNode propertyNode && (!propertyNode.IsPublicAPI || !IsAccessible(propertyNode.PropertyDefinition)))
- return false;
-
- if (node is MethodTreeNode methodNode && (!methodNode.IsPublicAPI || !IsAccessible(methodNode.MethodDefinition) || IsDelegateOrEnumMember(methodNode.MethodDefinition)))
- return false;
-
- if (node is NamespaceTreeNode namespaceNode && string.IsNullOrEmpty(namespaceNode.Name))
- return false;
- }
-
- return true;
- }
-
- bool IsAccessible(IEntity entity)
- {
- if (entity.DeclaringTypeDefinition == null)
- return false;
- switch (entity.DeclaringTypeDefinition.Accessibility)
- {
- case Accessibility.Public:
- case Accessibility.Protected:
- case Accessibility.ProtectedOrInternal:
- return true;
- default:
- return false;
- }
- }
-
- bool IsDelegateOrEnumMember(IMember member)
- {
- if (member.DeclaringTypeDefinition == null)
- return false;
- switch (member.DeclaringTypeDefinition.Kind)
- {
- case TypeKind.Delegate:
- case TypeKind.Enum:
- return true;
- default:
- return false;
- }
- }
-
- public void Execute(TextViewContext context)
- {
- if (context.SelectedTreeNodes != null)
- {
- foreach (ILSpyTreeNode node in context.SelectedTreeNodes)
- {
- SearchMsdn(node);
- }
- }
- }
-
- public static void SearchMsdn(ILSpyTreeNode node)
- {
- var address = string.Empty;
-
- if (node is NamespaceTreeNode namespaceNode)
- {
- address = string.Format(msdnAddress, namespaceNode.Name);
- }
- else if (node is IMemberTreeNode memberNode)
- {
- var member = memberNode.Member;
- var memberName = member.ReflectionName.Replace('`', '-').Replace('+', '.');
- if (memberName.EndsWith("..ctor", System.StringComparison.Ordinal))
- memberName = memberName.Substring(0, memberName.Length - 5) + "-ctor";
-
- address = string.Format(msdnAddress, memberName);
- }
-
- address = address.ToLower();
- if (!string.IsNullOrEmpty(address))
- GlobalUtils.OpenLink(address);
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Commands/SelectPdbContextMenuEntry.cs b/ILSpy/Commands/SelectPdbContextMenuEntry.cs
deleted file mode 100644
index f0ac31244..000000000
--- a/ILSpy/Commands/SelectPdbContextMenuEntry.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2018 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Composition;
-using System.IO;
-using System.Linq;
-
-using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpy.TreeNodes;
-
-using Microsoft.Win32;
-namespace ICSharpCode.ILSpy
-{
- [ExportContextMenuEntry(Header = nameof(Resources.SelectPDB))]
- [Shared]
- class SelectPdbContextMenuEntry(AssemblyTreeModel assemblyTreeModel) : IContextMenuEntry
- {
- public async void Execute(TextViewContext context)
- {
- var assembly = (context.SelectedTreeNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly;
- if (assembly == null)
- return;
- OpenFileDialog dlg = new OpenFileDialog();
- dlg.FileName = WholeProjectDecompiler.CleanUpFileName(assembly.ShortName, ".pdb");
- dlg.Filter = Resources.PortablePDBPdbAllFiles;
- dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName);
- if (dlg.ShowDialog() != true)
- return;
-
- using (context.TreeView.LockUpdates())
- {
- await assembly.LoadDebugInfo(dlg.FileName);
- }
-
- var node = (AssemblyTreeNode)assemblyTreeModel.FindNodeByPath(new[] { assembly.FileName }, true);
- node.UpdateToolTip();
- assemblyTreeModel.SelectNode(node);
- assemblyTreeModel.RefreshDecompiledView();
- }
-
- public bool IsEnabled(TextViewContext context) => true;
-
- public bool IsVisible(TextViewContext context)
- {
- return context.SelectedTreeNodes?.Length == 1
- && context.SelectedTreeNodes?.FirstOrDefault() is AssemblyTreeNode asm
- && asm.LoadedAssembly.IsLoadedAsValidAssembly;
- }
- }
-}
diff --git a/ILSpy/Commands/SetThemeCommand.cs b/ILSpy/Commands/SetThemeCommand.cs
deleted file mode 100644
index aa1e7d46a..000000000
--- a/ILSpy/Commands/SetThemeCommand.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-
-using System.Composition;
-
-namespace ICSharpCode.ILSpy.Commands
-{
- [Export]
- [Shared]
- public class SetThemeCommand(SettingsService settingsService) : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- if (parameter is string theme)
- {
- settingsService.SessionSettings.Theme = theme;
- }
- }
- }
-}
diff --git a/ILSpy/Commands/ShowCFGContextMenuEntry.cs b/ILSpy/Commands/ShowCFGContextMenuEntry.cs
deleted file mode 100644
index c936c74d4..000000000
--- a/ILSpy/Commands/ShowCFGContextMenuEntry.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Composition;
-using System.Windows;
-
-using ICSharpCode.Decompiler.FlowAnalysis;
-using ICSharpCode.Decompiler.IL;
-using ICSharpCode.Decompiler.IL.ControlFlow;
-
-namespace ICSharpCode.ILSpy.Commands
-{
-#if DEBUG
- [ExportContextMenuEntry(Header = "DEBUG -- Show CFG")]
- [Shared]
- internal class ShowCFGContextMenuEntry : IContextMenuEntry
- {
- public void Execute(TextViewContext context)
- {
- try
- {
- var container = (BlockContainer)context.Reference.Reference;
- var cfg = new ControlFlowGraph(container);
- ExportGraph(cfg.Nodes).Show();
- }
- catch (Exception ex)
- {
- MessageBox.Show("Error generating CFG - requires GraphViz dot.exe in PATH" + Environment.NewLine + Environment.NewLine + ex.ToString());
- }
- }
-
- public bool IsEnabled(TextViewContext context)
- {
- return context.Reference?.Reference is BlockContainer;
- }
-
- public bool IsVisible(TextViewContext context)
- {
- return context.Reference?.Reference is BlockContainer;
- }
-
- internal static GraphVizGraph ExportGraph(IReadOnlyList nodes, Func labelFunc = null)
- {
- if (labelFunc == null)
- {
- labelFunc = node => {
- var block = node.UserData as Block;
- return block != null ? block.Label : node.UserData?.ToString();
- };
- }
- GraphVizGraph g = new GraphVizGraph();
- GraphVizNode[] n = new GraphVizNode[nodes.Count];
- for (int i = 0; i < n.Length; i++)
- {
- n[i] = new GraphVizNode(nodes[i].UserIndex);
- n[i].shape = "box";
- n[i].label = labelFunc(nodes[i]);
- g.AddNode(n[i]);
- }
- foreach (var source in nodes)
- {
- foreach (var target in source.Successors)
- {
- g.AddEdge(new GraphVizEdge(source.UserIndex, target.UserIndex));
- }
- if (source.ImmediateDominator != null)
- {
- g.AddEdge(
- new GraphVizEdge(source.ImmediateDominator.UserIndex, source.UserIndex) {
- color = "green"
- });
- }
- }
- return g;
- }
- }
-#endif
-}
diff --git a/ILSpy/Commands/ShowPane.cs b/ILSpy/Commands/ShowPane.cs
deleted file mode 100644
index c82356b74..000000000
--- a/ILSpy/Commands/ShowPane.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.ViewModels;
-
-namespace ICSharpCode.ILSpy.Commands
-{
- class ToolPaneCommand(string contentId, DockWorkspace dockWorkspace) : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- dockWorkspace.ShowToolPane(contentId);
- }
- }
-
- class TabPageCommand(TabPageModel model, DockWorkspace dockWorkspace) : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- // ensure the tab control is focused before setting the active tab page, else the tab will not be focused
- dockWorkspace.ActiveTabPage?.Focus();
- // reset first, else clicking on the already active tab will not focus the tab and the menu checkmark will not be updated
- dockWorkspace.ActiveTabPage = null;
- dockWorkspace.ActiveTabPage = model;
- }
- }
-}
\ No newline at end of file
diff --git a/ILSpy/Commands/SimpleCommand.cs b/ILSpy/Commands/SimpleCommand.cs
deleted file mode 100644
index f57d07571..000000000
--- a/ILSpy/Commands/SimpleCommand.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections;
-using System.Windows.Data;
-using System.Windows.Input;
-
-namespace ICSharpCode.ILSpy
-{
- public abstract class SimpleCommand : ICommand
- {
- public event EventHandler CanExecuteChanged {
- add { CommandManager.RequerySuggested += value; }
- remove { CommandManager.RequerySuggested -= value; }
- }
-
- public abstract void Execute(object parameter);
-
- public virtual bool CanExecute(object parameter)
- {
- return true;
- }
- }
-
- public interface IProvideParameterBinding
- {
- Binding ParameterBinding { get; }
- }
-
- public interface IProvideParameterList
- {
- IEnumerable ParameterList { get; }
- object GetParameterText(object parameter);
- }
-}
diff --git a/ILSpy/Commands/SortAssemblyListCommand.cs b/ILSpy/Commands/SortAssemblyListCommand.cs
deleted file mode 100644
index 8a62182bc..000000000
--- a/ILSpy/Commands/SortAssemblyListCommand.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Composition;
-
-using ICSharpCode.ILSpy.AssemblyTree;
-using ICSharpCode.ILSpy.Properties;
-using ICSharpCode.ILSpyX;
-using ICSharpCode.ILSpyX.TreeView;
-
-namespace ICSharpCode.ILSpy
-{
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._View), Header = nameof(Resources.SortAssembly_listName), MenuIcon = "Images/Sort", MenuCategory = nameof(Resources.View))]
- [ExportToolbarCommand(ToolTip = nameof(Resources.SortAssemblyListName), ToolbarIcon = "Images/Sort", ToolbarCategory = nameof(Resources.View))]
- [Shared]
- sealed class SortAssemblyListCommand(AssemblyTreeModel assemblyTreeModel) : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- assemblyTreeModel.SortAssemblyList();
- }
- }
-
- [ExportMainMenuCommand(ParentMenuID = nameof(Resources._View), Header = nameof(Resources._CollapseTreeNodes), MenuIcon = "Images/CollapseAll", MenuCategory = nameof(Resources.View))]
- [ExportToolbarCommand(ToolTip = nameof(Resources.CollapseTreeNodes), ToolbarIcon = "Images/CollapseAll", ToolbarCategory = nameof(Resources.View))]
- [Shared]
- sealed class CollapseAllCommand(AssemblyTreeModel assemblyTreeModel) : SimpleCommand
- {
- public override void Execute(object parameter)
- {
- assemblyTreeModel.CollapseAll();
-
- }
- }
-}
diff --git a/ILSpy/ContextMenuEntry.cs b/ILSpy/ContextMenuEntry.cs
deleted file mode 100644
index a88812fca..000000000
--- a/ILSpy/ContextMenuEntry.cs
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Composition;
-using System.Linq;
-using System.Windows;
-using System.Windows.Controls;
-
-using ICSharpCode.AvalonEdit;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpyX.Search;
-using ICSharpCode.ILSpy.Controls.TreeView;
-using ICSharpCode.ILSpyX.TreeView;
-
-using TomsToolbox.Composition;
-using TomsToolbox.Essentials;
-using TomsToolbox.Wpf.Composition;
-
-namespace ICSharpCode.ILSpy
-{
- public interface IContextMenuEntry
- {
- bool IsVisible(TextViewContext context);
- bool IsEnabled(TextViewContext context);
- void Execute(TextViewContext context);
- }
-
- public class TextViewContext
- {
- ///
- /// Returns the selected nodes in the tree view.
- /// Returns null, if context menu does not belong to a tree view.
- ///
- public SharpTreeNode[] SelectedTreeNodes { get; private set; }
-
- ///
- /// Returns the tree view the context menu is assigned to.
- /// Returns null, if context menu is not assigned to a tree view.
- ///
- public SharpTreeView TreeView { get; private set; }
-
- ///
- /// Returns the text view the context menu is assigned to.
- /// Returns null, if context menu is not assigned to a text view.
- ///
- public DecompilerTextView TextView { get; private set; }
-
- ///
- /// Returns the list box the context menu is assigned to.
- /// Returns null, if context menu is not assigned to a list box.
- ///
- public ListBox ListBox { get; private set; }
-
- ///
- /// Returns the data grid the context menu is assigned to.
- /// Returns null, if context menu is not assigned to a data grid.
- ///
- public DataGrid DataGrid { get; private set; }
-
- ///
- /// Returns the reference the mouse cursor is currently hovering above.
- /// Returns null, if there was no reference found.
- ///
- public ReferenceSegment Reference { get; private set; }
-
- ///
- /// Returns the position in TextView the mouse cursor is currently hovering above.
- /// Returns null, if TextView returns null;
- ///
- public TextViewPosition? Position { get; private set; }
-
- ///
- /// Returns the original source of the context menu event.
- ///
- public DependencyObject OriginalSource { get; private set; }
-
- public static TextViewContext Create(ContextMenuEventArgs eventArgs, SharpTreeView treeView = null, DecompilerTextView textView = null, ListBox listBox = null, DataGrid dataGrid = null)
- {
- ReferenceSegment reference;
-
- if (textView is not null)
- {
- reference = textView.GetReferenceSegmentAtMousePosition();
- }
- else
- {
- reference = (listBox?.SelectedItem ?? dataGrid?.SelectedItem) switch {
- SearchResult searchResult => new() { Reference = searchResult.Reference },
- TreeNodes.IMemberTreeNode treeNode => new() { Reference = treeNode.Member }, { } value => new() { Reference = value },
- _ => null
- };
- }
-
- var position = textView?.GetPositionFromMousePosition();
- var selectedTreeNodes = treeView?.GetTopLevelSelection().ToArray();
-
- return new() {
- ListBox = listBox,
- DataGrid = dataGrid,
- TreeView = treeView,
- TextView = textView,
- SelectedTreeNodes = selectedTreeNodes,
- Reference = reference,
- Position = position,
- OriginalSource = eventArgs.OriginalSource as DependencyObject
- };
- }
- }
-
- public interface IContextMenuEntryMetadata
- {
- string MenuID { get; }
- string ParentMenuID { get; }
- string Icon { get; }
- string Header { get; }
- string Category { get; }
- string InputGestureText { get; }
-
- double Order { get; }
- }
-
- [MetadataAttribute]
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
- public class ExportContextMenuEntryAttribute : ExportAttribute, IContextMenuEntryMetadata
- {
- public ExportContextMenuEntryAttribute()
- : base(typeof(IContextMenuEntry))
- {
- // entries default to end of menu unless given specific order position
- Order = double.MaxValue;
- }
- ///
- /// Gets/Sets the ID of this menu item. Menu entries are not required to have an ID,
- /// however, setting it allows to declare nested menu structures.
- /// Plugin authors are advised to use GUIDs as identifiers to prevent conflicts.
- ///
- /// NOTE: Defining cycles (for example by accidentally setting equal to )
- /// will lead to a stack-overflow and crash of ILSpy at startup.
- ///
- public string MenuID { get; set; }
- ///
- /// Gets/Sets the parent of this menu item. All menu items sharing the same parent will be displayed as sub-menu items.
- /// If this property is set to , the menu item is displayed in the top-level menu.
- ///
- /// NOTE: Defining cycles (for example by accidentally setting equal to )
- /// will lead to a stack-overflow and crash of ILSpy at startup.
- ///
- public string ParentMenuID { get; set; }
- public string Icon { get; set; }
- public string Header { get; set; }
- public string Category { get; set; }
- public string InputGestureText { get; set; }
- public double Order { get; set; }
- }
-
- internal class ContextMenuProvider
- {
- private static readonly WeakEventSource ContextMenuClosedEventSource = new();
-
- public static event EventHandler ContextMenuClosed {
- add => ContextMenuClosedEventSource.Subscribe(value);
- remove => ContextMenuClosedEventSource.Unsubscribe(value);
- }
-
- ///
- /// Enables extensible context menu support for the specified tree view.
- ///
- public static void Add(SharpTreeView treeView)
- {
- var provider = new ContextMenuProvider(treeView);
- treeView.ContextMenuOpening += provider.treeView_ContextMenuOpening;
- // Context menu is shown only when the ContextMenu property is not null before the
- // ContextMenuOpening event handler is called.
- treeView.ContextMenu = new ContextMenu();
- }
-
- public static void Add(DecompilerTextView textView)
- {
- var provider = new ContextMenuProvider(textView);
- textView.ContextMenuOpening += provider.textView_ContextMenuOpening;
- // Context menu is shown only when the ContextMenu property is not null before the
- // ContextMenuOpening event handler is called.
- textView.ContextMenu = new ContextMenu();
- }
-
- public static void Add(ListBox listBox)
- {
- var provider = new ContextMenuProvider(listBox);
- listBox.ContextMenuOpening += provider.listBox_ContextMenuOpening;
- listBox.ContextMenu = new ContextMenu();
- }
-
- public static void Add(DataGrid dataGrid)
- {
- var provider = new ContextMenuProvider(dataGrid);
- dataGrid.ContextMenuOpening += provider.dataGrid_ContextMenuOpening;
- dataGrid.ContextMenu = new ContextMenu();
- }
-
- readonly Control control;
- readonly SharpTreeView treeView;
- readonly DecompilerTextView textView;
- readonly ListBox listBox;
- readonly DataGrid dataGrid;
- readonly IExport[] entries;
-
- private ContextMenuProvider(Control control)
- {
- entries = control.GetExportProvider().GetExports().ToArray();
-
- this.control = control;
- }
-
- ContextMenuProvider(DecompilerTextView textView)
- : this((Control)textView)
- {
- this.textView = textView ?? throw new ArgumentNullException(nameof(textView));
- }
-
- ContextMenuProvider(SharpTreeView treeView)
- : this((Control)treeView)
- {
- this.treeView = treeView ?? throw new ArgumentNullException(nameof(treeView));
- }
-
- ContextMenuProvider(ListBox listBox)
- : this((Control)listBox)
- {
- this.listBox = listBox ?? throw new ArgumentNullException(nameof(listBox));
- }
-
- ContextMenuProvider(DataGrid dataGrid)
- : this((Control)dataGrid)
- {
- this.dataGrid = dataGrid ?? throw new ArgumentNullException(nameof(dataGrid));
- }
-
- void treeView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
- {
- var context = TextViewContext.Create(e, treeView: treeView);
- if (context.SelectedTreeNodes.Length == 0)
- {
- e.Handled = true; // don't show the menu
- return;
- }
-
- if (ShowContextMenu(context, out var menu))
- treeView.ContextMenu = menu;
- else
- // hide the context menu.
- e.Handled = true;
- }
-
- void textView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
- {
- var context = TextViewContext.Create(e, textView: textView);
- if (ShowContextMenu(context, out var menu))
- textView.ContextMenu = menu;
- else
- // hide the context menu.
- e.Handled = true;
- }
-
- void listBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
- {
- var context = TextViewContext.Create(e, listBox: listBox);
- if (ShowContextMenu(context, out var menu))
- listBox.ContextMenu = menu;
- else
- // hide the context menu.
- e.Handled = true;
- }
-
- void dataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
- {
- var context = TextViewContext.Create(e, dataGrid: dataGrid);
- if (ShowContextMenu(context, out var menu))
- dataGrid.ContextMenu = menu;
- else
- // hide the context menu.
- e.Handled = true;
- }
-
- bool ShowContextMenu(TextViewContext context, out ContextMenu menu)
- {
- // Closing event is raised on the control where mouse is clicked, not on the control that opened the menu, so we hook on the global window event.
- var window = Window.GetWindow(control)!;
- window.ContextMenuClosing += ContextMenu_Closing;
-
- void ContextMenu_Closing(object sender, EventArgs e)
- {
- window.ContextMenuClosing -= ContextMenu_Closing;
- ContextMenuClosedEventSource.Raise(this, EventArgs.Empty);
- }
-
- menu = new ContextMenu();
-
- var menuGroups = new Dictionary[]>();
- IExport[] topLevelGroup = null;
- foreach (var group in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.ParentMenuID))
- {
- if (group.Key == null)
- {
- topLevelGroup = group.ToArray();
- }
- else
- {
- menuGroups.Add(group.Key, group.ToArray());
- }
- }
- BuildMenu(topLevelGroup ?? Array.Empty>(), menu.Items);
- return menu.Items.Count > 0;
-
- void BuildMenu(IExport[] menuGroup, ItemCollection parent)
- {
- foreach (var category in menuGroup.GroupBy(c => c.Metadata.Category))
- {
- var needSeparatorForCategory = parent.Count > 0;
- foreach (var entryPair in category)
- {
- var entry = entryPair.Value;
- if (entry.IsVisible(context))
- {
- if (needSeparatorForCategory)
- {
- parent.Add(new Separator());
- needSeparatorForCategory = false;
- }
- var menuItem = new MenuItem();
- menuItem.Header = ResourceHelper.GetString(entryPair.Metadata.Header);
- menuItem.InputGestureText = entryPair.Metadata.InputGestureText;
- if (!string.IsNullOrEmpty(entryPair.Metadata.Icon))
- {
- menuItem.Icon = new Image {
- Width = 16,
- Height = 16,
- Source = Images.Load(entryPair.Value, entryPair.Metadata.Icon)
- };
- }
- if (entryPair.Value.IsEnabled(context))
- {
- menuItem.Click += delegate { entry.Execute(context); };
- }
- else
- menuItem.IsEnabled = false;
- parent.Add(menuItem);
-
- if (entryPair.Metadata.MenuID != null && menuGroups.TryGetValue(entryPair.Metadata.MenuID, out var group))
- {
- BuildMenu(group, menuItem.Items);
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/ILSpy/Controls/CollapsiblePanel.cs b/ILSpy/Controls/CollapsiblePanel.cs
deleted file mode 100644
index bed3dd450..000000000
--- a/ILSpy/Controls/CollapsiblePanel.cs
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Input;
-using System.Windows.Media.Animation;
-using System.Windows.Threading;
-
-namespace ICSharpCode.ILSpy.Controls
-{
- ///
- /// Allows animated collapsing of the content of this panel.
- ///
- public class CollapsiblePanel : ContentControl
- {
- static CollapsiblePanel()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(CollapsiblePanel),
- new FrameworkPropertyMetadata(typeof(CollapsiblePanel)));
- FocusableProperty.OverrideMetadata(typeof(CollapsiblePanel),
- new FrameworkPropertyMetadata(false));
- }
-
- public static readonly DependencyProperty IsCollapsedProperty = DependencyProperty.Register(
- "IsCollapsed", typeof(bool), typeof(CollapsiblePanel),
- new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsCollapsedChanged)));
-
- public bool IsCollapsed {
- get { return (bool)GetValue(IsCollapsedProperty); }
- set { SetValue(IsCollapsedProperty, value); }
- }
-
- public static readonly DependencyProperty CollapseOrientationProperty =
- DependencyProperty.Register("CollapseOrientation", typeof(Orientation), typeof(CollapsiblePanel),
- new FrameworkPropertyMetadata(Orientation.Vertical));
-
- public Orientation CollapseOrientation {
- get { return (Orientation)GetValue(CollapseOrientationProperty); }
- set { SetValue(CollapseOrientationProperty, value); }
- }
-
- public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
- "Duration", typeof(TimeSpan), typeof(CollapsiblePanel),
- new UIPropertyMetadata(TimeSpan.FromMilliseconds(250)));
-
- ///
- /// The duration in milliseconds of the animation.
- ///
- public TimeSpan Duration {
- get { return (TimeSpan)GetValue(DurationProperty); }
- set { SetValue(DurationProperty, value); }
- }
-
- protected internal static readonly DependencyProperty AnimationProgressProperty = DependencyProperty.Register(
- "AnimationProgress", typeof(double), typeof(CollapsiblePanel),
- new FrameworkPropertyMetadata(1.0));
-
- ///
- /// Value between 0 and 1 specifying how far the animation currently is.
- ///
- protected internal double AnimationProgress {
- get { return (double)GetValue(AnimationProgressProperty); }
- set { SetValue(AnimationProgressProperty, value); }
- }
-
- protected internal static readonly DependencyProperty AnimationProgressXProperty = DependencyProperty.Register(
- "AnimationProgressX", typeof(double), typeof(CollapsiblePanel),
- new FrameworkPropertyMetadata(1.0));
-
- ///
- /// Value between 0 and 1 specifying how far the animation currently is.
- ///
- protected internal double AnimationProgressX {
- get { return (double)GetValue(AnimationProgressXProperty); }
- set { SetValue(AnimationProgressXProperty, value); }
- }
-
- protected internal static readonly DependencyProperty AnimationProgressYProperty = DependencyProperty.Register(
- "AnimationProgressY", typeof(double), typeof(CollapsiblePanel),
- new FrameworkPropertyMetadata(1.0));
-
- ///
- /// Value between 0 and 1 specifying how far the animation currently is.
- ///
- protected internal double AnimationProgressY {
- get { return (double)GetValue(AnimationProgressYProperty); }
- set { SetValue(AnimationProgressYProperty, value); }
- }
-
- static void OnIsCollapsedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- ((CollapsiblePanel)d).SetupAnimation((bool)e.NewValue);
- }
-
- void SetupAnimation(bool isCollapsed)
- {
- if (this.IsLoaded)
- {
- // If the animation is already running, calculate remaining portion of the time
- double currentProgress = AnimationProgress;
- if (!isCollapsed)
- {
- currentProgress = 1.0 - currentProgress;
- }
-
- DoubleAnimation animation = new DoubleAnimation();
- animation.To = isCollapsed ? 0.0 : 1.0;
- animation.Duration = TimeSpan.FromSeconds(Duration.TotalSeconds * currentProgress);
- animation.FillBehavior = FillBehavior.HoldEnd;
-
- this.BeginAnimation(AnimationProgressProperty, animation);
- if (CollapseOrientation == Orientation.Horizontal)
- {
- this.BeginAnimation(AnimationProgressXProperty, animation);
- this.AnimationProgressY = 1.0;
- }
- else
- {
- this.AnimationProgressX = 1.0;
- this.BeginAnimation(AnimationProgressYProperty, animation);
- }
- }
- else
- {
- this.AnimationProgress = isCollapsed ? 0.0 : 1.0;
- this.AnimationProgressX = (CollapseOrientation == Orientation.Horizontal) ? this.AnimationProgress : 1.0;
- this.AnimationProgressY = (CollapseOrientation == Orientation.Vertical) ? this.AnimationProgress : 1.0;
- }
- }
- }
-
- sealed class CollapsiblePanelProgressToVisibilityConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- if (value is double)
- return (double)value > 0 ? Visibility.Visible : Visibility.Collapsed;
- else
- return Visibility.Visible;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-
- public class SelfCollapsingPanel : CollapsiblePanel
- {
- public static readonly DependencyProperty CanCollapseProperty =
- DependencyProperty.Register("CanCollapse", typeof(bool), typeof(SelfCollapsingPanel),
- new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnCanCollapseChanged)));
-
- public bool CanCollapse {
- get { return (bool)GetValue(CanCollapseProperty); }
- set { SetValue(CanCollapseProperty, value); }
- }
-
- static void OnCanCollapseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- SelfCollapsingPanel panel = (SelfCollapsingPanel)d;
- if ((bool)e.NewValue)
- {
- if (!panel.HeldOpenByMouse)
- panel.IsCollapsed = true;
- }
- else
- {
- panel.IsCollapsed = false;
- }
- }
-
- bool HeldOpenByMouse {
- get { return IsMouseOver || IsMouseCaptureWithin; }
- }
-
- protected override void OnMouseLeave(MouseEventArgs e)
- {
- base.OnMouseLeave(e);
- if (CanCollapse && !HeldOpenByMouse)
- IsCollapsed = true;
- }
-
- protected override void OnLostMouseCapture(MouseEventArgs e)
- {
- base.OnLostMouseCapture(e);
- if (CanCollapse && !HeldOpenByMouse)
- IsCollapsed = true;
- }
- }
-}
diff --git a/ILSpy/Controls/CultureSelectionConverter.cs b/ILSpy/Controls/CultureSelectionConverter.cs
deleted file mode 100644
index f8b7c2389..000000000
--- a/ILSpy/Controls/CultureSelectionConverter.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2021 Siegfried Pammer
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE
-
-using System;
-using System.Globalization;
-using System.Windows.Data;
-using System.Windows.Markup;
-
-namespace ICSharpCode.ILSpy.Controls
-{
- public class CultureSelectionConverter : MarkupExtension, IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value is string s)
- return s.Equals(parameter);
- return value == parameter;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if ((bool)value)
- return parameter;
- return Binding.DoNothing;
- }
-
- public override object ProvideValue(IServiceProvider serviceProvider)
- {
- return this;
- }
- }
-}
diff --git a/ILSpy/Controls/CustomDialog.cs b/ILSpy/Controls/CustomDialog.cs
deleted file mode 100644
index 1e180c517..000000000
--- a/ILSpy/Controls/CustomDialog.cs
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Drawing;
-using System.Windows.Forms;
-
-namespace ICSharpCode.ILSpy.Controls
-{
- public sealed class CustomDialog : System.Windows.Forms.Form
- {
- System.Windows.Forms.Label label;
- System.Windows.Forms.Panel panel;
- int acceptButton;
- int cancelButton;
- int result = -1;
-
- ///
- /// Gets the index of the button pressed.
- ///
- public int Result {
- get {
- return result;
- }
- }
-
- public CustomDialog(string caption, string message, int acceptButton, int cancelButton, string[] buttonLabels)
- {
- this.SuspendLayout();
- MyInitializeComponent();
-
- this.Icon = null;
- this.acceptButton = acceptButton;
- this.cancelButton = cancelButton;
- this.Text = caption;
-
- using (Graphics g = this.CreateGraphics())
- {
- Size size = TextRenderer.MeasureText(message, label.Font, new((int)(Screen.FromControl(this).WorkingArea.Width * 0.9), int.MaxValue), TextFormatFlags.NoPrefix | TextFormatFlags.WordBreak);
- Size clientSize = new Size((int)Math.Ceiling(size.Width * 96 / g.DpiX) + DockPadding.Left + DockPadding.Right, (int)Math.Ceiling(size.Height * 96 / g.DpiY) + DockPadding.Top + DockPadding.Bottom);
- Button[] buttons = new Button[buttonLabels.Length];
- int[] positions = new int[buttonLabels.Length];
- int pos = 0;
- for (int i = 0; i < buttons.Length; i++)
- {
- Button newButton = new Button();
- newButton.FlatStyle = FlatStyle.System;
- newButton.Tag = i;
- string buttonLabel = buttonLabels[i];
- newButton.Text = buttonLabel;
- newButton.Click += new EventHandler(ButtonClick);
- Size buttonSize = TextRenderer.MeasureText(buttonLabel, newButton.Font);
- newButton.Width = Math.Max(newButton.Width, ((int)Math.Ceiling(buttonSize.Width * 96 / g.DpiX / 8.0) + 1) * 8);
- positions[i] = pos;
- buttons[i] = newButton;
- pos += newButton.Width + 4;
- }
- if (acceptButton >= 0)
- {
- AcceptButton = buttons[acceptButton];
- }
- if (cancelButton >= 0)
- {
- CancelButton = buttons[cancelButton];
- }
-
- pos += 4; // add space before first button
- // (we don't start with pos=4 because this space doesn't belong to the button panel)
-
- if (pos > clientSize.Width)
- {
- clientSize.Width = pos;
- }
- clientSize.Height += panel.Height;
- this.ClientSize = clientSize;
- int start = (clientSize.Width - pos) / 2;
- for (int i = 0; i < buttons.Length; i++)
- {
- buttons[i].Location = new Point(start + positions[i], 4);
- }
- panel.Controls.AddRange(buttons);
- }
- label.Text = message;
-
- this.ResumeLayout(false);
- }
-
- protected override void OnKeyDown(KeyEventArgs e)
- {
- if (cancelButton == -1 && e.KeyCode == Keys.Escape)
- {
- this.Close();
- }
- else if (e.KeyCode == Keys.C && e.Control)
- {
- Clipboard.SetText(this.Text + Environment.NewLine + label.Text);
- }
- }
-
- void ButtonClick(object sender, EventArgs e)
- {
- result = (int)((Control)sender).Tag;
- this.Close();
- }
-
- ///
- /// This method is required for Windows Forms designer support.
- /// Do not change the method contents inside the source code editor. The Forms designer might
- /// not be able to load this method if it was changed manually.
- ///
- void MyInitializeComponent()
- {
- this.panel = new System.Windows.Forms.Panel();
- this.label = new System.Windows.Forms.Label();
- //
- // panel
- //
- this.panel.Dock = System.Windows.Forms.DockStyle.Bottom;
- this.panel.Location = new System.Drawing.Point(4, 80);
- this.panel.Name = "panel";
- this.panel.Size = new System.Drawing.Size(266, 32);
- this.panel.TabIndex = 0;
- //
- // label
- //
- this.label.Dock = System.Windows.Forms.DockStyle.Fill;
- this.label.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.label.Location = new System.Drawing.Point(4, 4);
- this.label.Name = "label";
- this.label.Size = new System.Drawing.Size(266, 76);
- this.label.TabIndex = 1;
- this.label.UseMnemonic = false;
- //
- // CustomDialog
- //
- this.ClientSize = new System.Drawing.Size(274, 112);
- this.Controls.Add(this.label);
- this.Controls.Add(this.panel);
- this.DockPadding.Left = 4;
- this.DockPadding.Right = 4;
- this.DockPadding.Top = 4;
- this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
- this.ShowInTaskbar = false;
- this.MaximizeBox = false;
- this.MinimizeBox = false;
- this.Name = "CustomDialog";
- this.KeyPreview = true;
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- this.Text = "CustomDialog";
- this.AutoScaleMode = AutoScaleMode.Dpi;
- this.AutoScaleDimensions = new SizeF(96, 96);
- }
- }
-}
diff --git a/ILSpy/Controls/ExtensionMethods.cs b/ILSpy/Controls/ExtensionMethods.cs
deleted file mode 100644
index 1ab16694e..000000000
--- a/ILSpy/Controls/ExtensionMethods.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Windows;
-using System.Windows.Markup;
-
-namespace ICSharpCode.ILSpy.Controls
-{
- ///
- /// ExtensionMethods used in ILSpy.
- ///
- public static class ExtensionMethods
- {
- ///
- /// Sets the value of a dependency property on using a markup extension.
- ///
- /// This method does not support markup extensions like x:Static that depend on
- /// having a XAML file as context.
- public static void SetValueToExtension(this DependencyObject targetObject, DependencyProperty property, MarkupExtension markupExtension)
- {
- // This method was copied from ICSharpCode.Core.Presentation (with permission to switch license to X11)
-
- if (targetObject == null)
- throw new ArgumentNullException(nameof(targetObject));
- if (property == null)
- throw new ArgumentNullException(nameof(property));
- if (markupExtension == null)
- throw new ArgumentNullException(nameof(markupExtension));
-
- var serviceProvider = new SetValueToExtensionServiceProvider(targetObject, property);
- targetObject.SetValue(property, markupExtension.ProvideValue(serviceProvider));
- }
-
- sealed class SetValueToExtensionServiceProvider : IServiceProvider, IProvideValueTarget
- {
- // This class was copied from ICSharpCode.Core.Presentation (with permission to switch license to X11)
-
- readonly DependencyObject targetObject;
- readonly DependencyProperty targetProperty;
-
- public SetValueToExtensionServiceProvider(DependencyObject targetObject, DependencyProperty property)
- {
- this.targetObject = targetObject;
- this.targetProperty = property;
- }
-
- public object GetService(Type serviceType)
- {
- if (serviceType == typeof(IProvideValueTarget))
- return this;
- else
- return null;
- }
-
- public object TargetObject {
- get { return targetObject; }
- }
-
- public object TargetProperty {
- get { return targetProperty; }
- }
- }
- }
-}
diff --git a/ILSpy/Controls/GridViewColumnAutoSize.cs b/ILSpy/Controls/GridViewColumnAutoSize.cs
deleted file mode 100644
index 8f5efb43e..000000000
--- a/ILSpy/Controls/GridViewColumnAutoSize.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Windows;
-using System.Windows.Controls;
-
-namespace ICSharpCode.ILSpy.Controls
-{
- ///
- /// This class adds the AutoWidth property to the WPF ListView.
- /// It supports a semi-colon-separated list of values, for each defined cell.
- /// Each value can either be a fixed size double, or a percentage.
- /// The sizes of columns with a percentage will be calculated from the
- /// remaining width (after assigning the fixed sizes).
- /// Examples: 50%;25%;25% or 30;100%;50
- ///
- public class GridViewColumnAutoSize
- {
- // This class was copied from ICSharpCode.Core.Presentation.
-
- public static readonly DependencyProperty AutoWidthProperty =
- DependencyProperty.RegisterAttached("AutoWidth", typeof(string), typeof(GridViewColumnAutoSize),
- new FrameworkPropertyMetadata(null, AutoWidthPropertyChanged));
-
- public static string GetAutoWidth(DependencyObject obj)
- {
- return (string)obj.GetValue(AutoWidthProperty);
- }
-
- public static void SetAutoWidth(DependencyObject obj, string value)
- {
- obj.SetValue(AutoWidthProperty, value);
- }
-
- static void AutoWidthPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
- {
- ListView grid = sender as ListView;
- if (grid == null)
- return;
- grid.SizeChanged += delegate (object listView, SizeChangedEventArgs e) {
- ListView lv = listView as ListView;
- if (lv == null)
- return;
- GridView v = lv.View as GridView;
- if (v == null)
- return;
- CalculateSizes(v, GetAutoWidth(lv), e.NewSize.Width);
- };
- GridView view = grid.View as GridView;
- if (view == null)
- return;
- CalculateSizes(view, args.NewValue as string, grid.ActualWidth);
- }
-
- static void CalculateSizes(GridView view, string sizeValue, double fullWidth)
- {
- string[] sizes = (sizeValue ?? "").Split(';');
-
- if (sizes.Length != view.Columns.Count)
- return;
- Dictionary> percentages = new Dictionary>();
- double remainingWidth = fullWidth - 30; // 30 is a good offset for the scrollbar
-
- for (int i = 0; i < view.Columns.Count; i++)
- {
- var column = view.Columns[i];
- double size;
- bool isPercentage = !double.TryParse(sizes[i], out size);
- if (isPercentage)
- {
- size = double.Parse(sizes[i].TrimEnd('%', ' '));
- percentages.Add(i, w => w * size / 100.0);
- }
- else
- {
- column.Width = size;
- remainingWidth -= size;
- }
- }
-
- if (remainingWidth < 0)
- return;
- foreach (var p in percentages)
- {
- var column = view.Columns[p.Key];
- column.Width = p.Value(remainingWidth);
- }
- }
- }
-}
diff --git a/ILSpy/Controls/MainMenu.xaml b/ILSpy/Controls/MainMenu.xaml
deleted file mode 100644
index dfb723166..000000000
--- a/ILSpy/Controls/MainMenu.xaml
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/ILSpy/Controls/MainMenu.xaml.cs b/ILSpy/Controls/MainMenu.xaml.cs
deleted file mode 100644
index 3bb7ad404..000000000
--- a/ILSpy/Controls/MainMenu.xaml.cs
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (c) 2024 Tom Englert for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System.Collections.Generic;
-using System.Composition;
-using System.Globalization;
-using System.Linq;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Input;
-
-using ICSharpCode.ILSpy.Commands;
-
-using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.ViewModels;
-
-using TomsToolbox.Composition;
-using TomsToolbox.ObservableCollections;
-using TomsToolbox.Wpf;
-using TomsToolbox.Wpf.Converters;
-
-namespace ICSharpCode.ILSpy.Controls
-{
- ///
- /// Interaction logic for MainMenu.xaml
- ///
- [Export]
- [NonShared]
- public partial class MainMenu
- {
- public MainMenu(SettingsService settingsService, IExportProvider exportProvider, DockWorkspace dockWorkspace)
- {
- SessionSettings = settingsService.SessionSettings;
-
- InitializeComponent();
-
- this.BeginInvoke(() => {
- InitMainMenu(Menu, exportProvider);
- InitWindowMenu(WindowMenuItem, Window.GetWindow(this)!.InputBindings, dockWorkspace);
- });
- }
-
- public SessionSettings SessionSettings { get; }
-
- static void InitMainMenu(Menu mainMenu, IExportProvider exportProvider)
- {
- var mainMenuCommands = exportProvider.GetExports("MainMenuCommand");
- // Start by constructing the individual flat menus
- var parentMenuItems = new Dictionary();
- var menuGroups = mainMenuCommands.OrderBy(c => c.Metadata?.MenuOrder).GroupBy(c => c.Metadata?.ParentMenuID).ToArray();
- foreach (var menu in menuGroups)
- {
- // Get or add the target menu item and add all items grouped by menu category
- var parentMenuItem = GetOrAddParentMenuItem(menu.Key, menu.Key);
- foreach (var category in menu.GroupBy(c => c.Metadata?.MenuCategory))
- {
- if (parentMenuItem.Items.Count > 0)
- {
- parentMenuItem.Items.Add(new Separator { Tag = category.Key });
- }
- foreach (var entry in category)
- {
- if (menuGroups.Any(g => g.Key == entry.Metadata?.MenuID))
- {
- var menuItem = GetOrAddParentMenuItem(entry.Metadata?.MenuID, entry.Metadata?.Header);
- // replace potential dummy text with real name
- menuItem.Header = ResourceHelper.GetString(entry.Metadata?.Header);
- parentMenuItem.Items.Add(menuItem);
- }
- else
- {
- var command = entry.Value;
-
- var menuItem = new MenuItem {
- Command = CommandWrapper.Unwrap(command),
- Tag = entry.Metadata?.MenuID,
- Header = ResourceHelper.GetString(entry.Metadata?.Header)
- };
-
- if (!string.IsNullOrEmpty(entry.Metadata?.MenuIcon))
- {
- menuItem.Icon = new Image {
- Width = 16,
- Height = 16,
- Source = Images.Load(command, entry.Metadata.MenuIcon)
- };
- }
-
- menuItem.IsEnabled = entry.Metadata?.IsEnabled ?? false;
- menuItem.InputGestureText = entry.Metadata?.InputGestureText;
-
- if (command is IProvideParameterBinding parameterBinding)
- {
- BindingOperations.SetBinding(menuItem, MenuItem.CommandParameterProperty, parameterBinding.ParameterBinding);
- }
-
- parentMenuItem.Items.Add(menuItem);
- }
- }
- }
- }
-
- foreach (var item in parentMenuItems.Values.Where(item => item.Parent == null))
- {
- mainMenu.Items.Add(item);
- }
-
- MenuItem GetOrAddParentMenuItem(string menuId, string resourceKey)
- {
- if (!parentMenuItems.TryGetValue(menuId, out var parentMenuItem))
- {
- var topLevelMenuItem = mainMenu.Items.OfType