mirror of https://github.com/icsharpcode/ILSpy.git
25 changed files with 850 additions and 1 deletions
@ -0,0 +1,100 @@
@@ -0,0 +1,100 @@
|
||||
# CLAUDE.md |
||||
|
||||
Guidance for Claude Code (and future Claude sessions) when working on ILSpy. |
||||
|
||||
## What this codebase is |
||||
|
||||
ILSpy is a cross-platform .NET assembly browser / decompiler built on **Avalonia 12**, on top of the cross-platform `ICSharpCode.ILSpyX` and `ICSharpCode.Decompiler` core libraries. The `ILSpy/` project IS the Avalonia UI — there is no separate "WPF version" in this tree. |
||||
|
||||
## Tech stack |
||||
|
||||
- **Avalonia 12** (not 11.x). |
||||
- **AvaloniaEdit** for the decompiled-code text view. |
||||
- **Dock** (wieslawsoltes/Dock) for the panel layout. NuGet id ≠ CLR namespace — `Dock.Controls.Recycling` lives in `Avalonia.Controls.Recycling`; decompile before guessing xmlns. |
||||
- **Avalonia.Xaml.Behaviors** for attached-behaviour glue. |
||||
- **Avalonia.ExtendedToolkit** (mameolan) for controls not in Avalonia core. |
||||
- **Simple** theme (not Fluent). Check `App.axaml` / csproj before assuming Fluent. Note that Simple's ComboBox chevron is `ToggleButton#toggle`, not `Border#HighlightBackground`. |
||||
- **Microsoft.Extensions.DependencyInjection** + **System.Composition** MEF directly, with a small bridge. Do **not** use TomsToolbox. |
||||
- **AvaloniaEdit theme** must be registered in `Application.Styles` via the StyleInclude or `TextEditor` renders 0×0. |
||||
- Central package management is enabled — every `PackageReference` needs a matching `PackageVersion` in `Directory.Packages.props`. |
||||
- Target framework: `net10.0` (cross-platform) for the main app and tests. `net10.0-windows` only for tests that intentionally exercise Windows-only behaviour. |
||||
|
||||
## Project structure |
||||
|
||||
Avalonia UI: |
||||
- `ILSpy/` — the Avalonia UI app |
||||
- `ILSpy.Tests/` — headless Avalonia UI tests (Avalonia.Headless.NUnit) |
||||
- `ILSpy.Tests.Windows/` — Windows-only UI tests (OS-gated; `net10.0-windows`) |
||||
- `ILSpy.ReadyToRun/` — ReadyToRun-viewer plugin, **ported to Avalonia** (`net10.0`; part of `ILSpy.Desktop.slnf`). Not legacy. |
||||
|
||||
Cross-platform core (decompiler engine + shared support): |
||||
- `ICSharpCode.Decompiler/` — core decompiler library (multi-targeted, cross-platform) |
||||
- `ICSharpCode.ILSpyX/` — shared UI-host-agnostic support library |
||||
- `ICSharpCode.BamlDecompiler/` — BAML parsing library |
||||
- `ICSharpCode.ILSpyCmd/` — CLI front-end (`ilspycmd`) |
||||
- `ICSharpCode.Decompiler.Tests/` + `ICSharpCode.Decompiler.TestRunner/` — decompiler test suite and its out-of-process runner |
||||
- `ICSharpCode.Decompiler.PowerShell/` — PowerShell cmdlets (`netstandard2.0`) |
||||
|
||||
Test support: |
||||
- `TestPlugin/` — sample plugin exercising the plugin-loading system (`net10.0-windows`) |
||||
- `TestFixtures.Resources/` — generates resource fixtures consumed by the decompiler tests |
||||
|
||||
Legacy / Windows-tied (porting backlog; do **not** modify unless explicitly asked to port them): |
||||
- `ILSpy.AddIn/`, `ILSpy.AddIn.VS2022/` — Visual Studio add-ins (`net472`) |
||||
- `ILSpy.Installer/` — WiX installer (`net472`) |
||||
- `ILSpy.BamlDecompiler.Tests/` — BAML-decompiler tests, still WPF/Windows-bound (`net11.0-windows`); there is **no** `ILSpy.BamlDecompiler/` project, only these tests |
||||
|
||||
Solutions & filters: `ILSpy.sln` builds everything; `ILSpy.XPlat.slnf` is the decompiler libs + `ilspycmd` + their tests (no UI — the Linux CI target); `ILSpy.Desktop.slnf` is the UI plus its dependencies and tests; `ILSpy.Installer.sln` / `ILSpy.VSExtensions.sln` cover the legacy packaging. |
||||
|
||||
## Code conventions |
||||
|
||||
- **Don't reference "WPF" in source or comments.** Describe what code does, not where it came from. "Mirrors WPF" comments rot once the legacy WPF tree is gone. |
||||
- **Don't invent.** Port what the previous app actually shipped, not every conceivable feature. Don't add Options-page settings that weren't there. |
||||
- **TDD for new features.** Write the failing test, show it red, implement, show it green. Never skip the red step. |
||||
- **Strict pattern matchers.** Decompilation pattern matchers should default to `∀` over the structurally guaranteed shape — loosen only when a legitimate fixture is rejected (capture it as a regression test first). |
||||
- **No silent returns in tests.** When an expected component is missing, assert and fail. Never `return` early to bypass the assertion. |
||||
- **ASCII-only in code and comments.** Do not use non-ASCII characters (em-dash, smart quotes, arrows, math symbols, etc.) unless genuinely necessary for what the code expresses. |
||||
- **en-US English** in all source code, comments, identifiers, and log/error strings. |
||||
|
||||
## Build / restore |
||||
|
||||
- After adding or bumping a `PackageReference`, regenerate lock files with `dotnet restore /p:RestoreEnablePackagePruning=false` so the lock files stay complete. |
||||
- The pre-commit hook runs `dotnet format` on the **whole solution**. New files must be CRLF (`unix2dos` after `Write`) or the hook rewrites them and breaks staging. |
||||
- **Partial commits need stash-and-pop.** The format hook only auto-formats when the staged set equals the working tree. Stash unstaged remainder before committing a subset. |
||||
|
||||
## Commit workflow |
||||
|
||||
- Subject: `Avalonia: <lowercase phrase>` for UI-side changes. **Keep it succinct** (target <= 72 chars). Subject says *what area*; the body carries the substance. |
||||
- **Body explains the *why*** and the non-diff context: the constraint, the prior incident, the decision, what was tried and rejected, the invariant that motivated the change. The diff already shows the *what* — don't restate it. |
||||
- `Fix #NNNN: ...` closes an issue. `#NNNN` references one without closing. |
||||
- **Small follow-up fixes against a commit still on the branch get squashed back** via `git commit --fixup` + `git rebase --autosquash`, not appended as "fix X" commits. |
||||
- **en-US English** in subject and body. ASCII-only unless a non-ASCII character is genuinely required for what the message describes. |
||||
- **AI attribution: use `Assisted-by:`, not `Co-Authored-By:`.** Following the Linux kernel's coding-assistants guidance (https://docs.kernel.org/process/coding-assistants.html#attribution), an AI-assisted commit ends with a trailer of the form `Assisted-by: AGENT_NAME:MODEL_VERSION:HARNESS` — agent, model id, and the harness that ran it, colon-separated, e.g. `Assisted-by: Claude:claude-opus-4-8:Claude Code`. Use the session's actual model id and harness. Don't list analysis/build tools. Do **not** add a `Co-Authored-By:` line for the AI, and an AI agent **must not** add a `Signed-off-by:` (only a human can certify the DCO). |
||||
- The parity trackers (`AVALONIA_PARITY_TODO.html`, `AVALONIA_PORT_TASKS.md`, `AVALONIA_PORT_TASKS.html`) are **intentionally untracked** -- never `git add` them. |
||||
|
||||
## Test discipline |
||||
|
||||
- Always run the test suite with `--report-trx` so failures survive: `dotnet test ILSpy.sln --report-trx`. Don't dismiss failures as flaky without first reproducing in isolation, then running repeatedly. |
||||
- After matcher / rewriter edits, **run the relevant tests, not just the build.** `dotnet build` green ≠ behaviour correct. |
||||
|
||||
## Framework-specific gotchas |
||||
|
||||
- **AvaloniaEdit hyperlinks.** Flip `Editor.Options.RequireControlModifierForHyperlinkClick=false` once on the editor; don't override `ConstructElementFromMatch` per generator. |
||||
- **AvaloniaEdit hover.** `OnQueryCursor` must **not** set `e.Handled=true`. `PointerHover` args are captured at hover-start, not at fire-time. |
||||
- **AvaloniaEdit TextView coords.** `GetPosition` wants document-visual coords (add `ScrollOffset`). Redraw `IBackgroundRenderer`s via `TextView.InvalidateLayer`. |
||||
- **Avalonia 12 clipboard.** `IClipboard.SetTextAsync` is an extension method — needs `using Avalonia.Input.Platform;` even when the namespace is already imported (`ClipboardExtensions` is a separate static class). |
||||
- **ProDataGrid hierarchical cell layout.** Use `Grid Auto/*` in `DataGridHierarchicalColumn` cell templates, not `StackPanel`. The first child gets clipped otherwise. |
||||
- **ProDataGrid two-way expanded sync.** Bind `HierarchicalOptions.IsExpandedPropertyPath` for model↔grid sync; don't hand-roll `NodeExpanded` / `PropertyChanged` plumbing. |
||||
- **ProDataGrid row drag-drop.** DataGrid-level `IsReadOnly` short-circuits the drag controller. Put `IsReadOnly` on the **column** instead. |
||||
- **Dock setup follows `samples/DockMvvmSample`.** `App.axaml` wiring, factory shape, `DockControl` markup, `ContextLocator` / `DockableLocator` should match the sample. Deviate only with a documented reason. |
||||
- **DockWorkspace tab routing.** Every navigation reuses the active tab (replacing in place if the type changes). Only "Open in new tab" and "Freeze tab" carve out new tabs. |
||||
- **Decompile-progress UI is an overlay.** Never wipe `Text` / `Foldings` / etc. to show a spinner; keep editor state intact so cancel falls back to it. |
||||
- **`ILSpyTraceListener`** surfaces `Debug.Assert` through the global dialog — keep it registered at startup. |
||||
|
||||
## Investigating dependencies |
||||
|
||||
- **Decompile NuGet packages with this repo's `ilspycmd`** to inspect dependency internals — don't grep binaries. |
||||
|
||||
## Onboarding new contributors |
||||
|
||||
If you're picking up this codebase fresh, read `Program.cs` → `App.axaml.cs` → `Views/MainWindow.axaml.cs` to trace startup, then `AssemblyTree/AssemblyListPane.axaml.cs` and `TextView/DecompilerTextView.axaml.cs` for the two main panes. The MEF composition graph in `AppEnv/AppComposition.cs` wires the rest. |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2026 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 Avalonia; |
||||
using Avalonia.Headless.NUnit; |
||||
|
||||
using AwesomeAssertions; |
||||
|
||||
using ILSpy; |
||||
|
||||
using NUnit.Framework; |
||||
|
||||
namespace ICSharpCode.ILSpy.Tests; |
||||
|
||||
// Sanity check that TestApp.base.Initialize() populates DataTemplates and Styles from
|
||||
// ILSpy/App.axaml. If this regresses, every UI-headless test that follows runs against an
|
||||
// unconfigured Application surface (no ViewLocator, no theme), failing in confusing ways.
|
||||
[TestFixture] |
||||
public class AppInitializationTests |
||||
{ |
||||
[AvaloniaTest] |
||||
public void TestApp_pulls_DataTemplates_from_App_axaml() |
||||
{ |
||||
var app = Application.Current!; |
||||
app.DataTemplates.Should().Contain(t => t is ViewLocator, |
||||
"App.axaml registers ViewLocator; base.Initialize() should propagate it onto TestApp."); |
||||
} |
||||
|
||||
[AvaloniaTest] |
||||
public void TestApp_pulls_Styles_from_App_axaml() |
||||
{ |
||||
var app = Application.Current!; |
||||
app.Styles.Should().NotBeEmpty( |
||||
"App.axaml registers a theme via Application.Styles; TestApp should inherit it."); |
||||
} |
||||
} |
||||
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
||||
<PropertyGroup> |
||||
<TargetFramework>net11.0</TargetFramework> |
||||
<OutputType>Exe</OutputType> |
||||
<Nullable>enable</Nullable> |
||||
<IsPackable>false</IsPackable> |
||||
<RootNamespace>ICSharpCode.ILSpy.Tests</RootNamespace> |
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> |
||||
</PropertyGroup> |
||||
|
||||
<ItemGroup> |
||||
<PackageReference Include="Avalonia" /> |
||||
<PackageReference Include="Avalonia.Headless.NUnit" /> |
||||
<PackageReference Include="Avalonia.Themes.Simple" /> |
||||
<PackageReference Include="NUnit" /> |
||||
<PackageReference Include="NUnit3TestAdapter" /> |
||||
<PackageReference Include="coverlet.MTP" /> |
||||
<PackageReference Include="Microsoft.Testing.Extensions.TrxReport" /> |
||||
<PackageReference Include="Microsoft.Testing.Extensions.VSTestBridge" /> |
||||
<PackageReference Include="AwesomeAssertions" /> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<ProjectReference Include="..\ILSpy\ILSpy.csproj" /> |
||||
</ItemGroup> |
||||
|
||||
</Project> |
||||
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
<Application xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
x:Class="ICSharpCode.ILSpy.Tests.TestApp" |
||||
RequestedThemeVariant="Default" /> |
||||
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2026 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 ICSharpCode.ILSpyX.Settings; |
||||
|
||||
using ProductionApp = global::ILSpy.App; |
||||
|
||||
namespace ICSharpCode.ILSpy.Tests; |
||||
|
||||
// Subclasses the production App and lets base.Initialize() populate this instance
|
||||
// from ILSpy/App.axaml (the XAML compiler's rewrite of Load(this) inside App.Initialize
|
||||
// targets App.axaml's compiled populate, so TestApp picks up the production Resources,
|
||||
// Styles, and DataTemplates without duplicating the XAML).
|
||||
public class TestApp : ProductionApp |
||||
{ |
||||
public override void Initialize() |
||||
{ |
||||
base.Initialize(); |
||||
} |
||||
|
||||
public override void OnFrameworkInitializationCompleted() |
||||
{ |
||||
var dir = Path.Combine(Path.GetTempPath(), "ILSpy.Tests", Guid.NewGuid().ToString("N")); |
||||
Directory.CreateDirectory(dir); |
||||
var configPath = Path.Combine(dir, "ILSpy.xml"); |
||||
ILSpySettings.SettingsFilePathProvider = () => configPath; |
||||
} |
||||
} |
||||
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2026 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 Avalonia; |
||||
using Avalonia.Headless; |
||||
|
||||
using ICSharpCode.ILSpy.Tests; |
||||
|
||||
[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))] |
||||
[assembly: AvaloniaTestIsolation(AvaloniaTestIsolationLevel.PerAssembly)] |
||||
|
||||
namespace ICSharpCode.ILSpy.Tests; |
||||
|
||||
public static class TestAppBuilder |
||||
{ |
||||
// Visible mode (debugger attached or ILSPY_TESTS_VISIBLE=1) flips Skia drawing on so
|
||||
// CaptureAndShow can save a real PNG; otherwise headless drawing keeps tests cheap.
|
||||
public static AppBuilder BuildAvaloniaApp() |
||||
{ |
||||
var visible = Debugger.IsAttached |
||||
|| string.Equals(Environment.GetEnvironmentVariable("ILSPY_TESTS_VISIBLE"), "1", StringComparison.Ordinal); |
||||
return AppBuilder.Configure<TestApp>() |
||||
.UseSkia() |
||||
.UseHeadless(new AvaloniaHeadlessPlatformOptions { |
||||
UseHeadlessDrawing = !visible, |
||||
}); |
||||
} |
||||
} |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2026 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.IO; |
||||
using System.Linq; |
||||
using System.Runtime.CompilerServices; |
||||
|
||||
using Avalonia.Controls; |
||||
using Avalonia.Headless; |
||||
using Avalonia.Threading; |
||||
|
||||
namespace ICSharpCode.ILSpy.Tests; |
||||
|
||||
public static class WindowExtensions |
||||
{ |
||||
/// <summary>Snapshots the window with Skia, writes a temp PNG, and opens it in the OS
|
||||
/// image viewer. No-op when <c>UseHeadlessDrawing</c> is true (CI default).</summary>
|
||||
public static void CaptureAndShow(this Window window, [CallerMemberName] string? label = null) |
||||
{ |
||||
ArgumentNullException.ThrowIfNull(window); |
||||
Dispatcher.UIThread.RunJobs(); |
||||
|
||||
var frame = window.CaptureRenderedFrame(); |
||||
if (frame is null) |
||||
return; |
||||
|
||||
var fileName = $"ILSpy.Tests-{Sanitize(label)}-{DateTime.Now:HHmmss-fff}.png"; |
||||
var path = Path.Combine(Path.GetTempPath(), fileName); |
||||
frame.Save(path); |
||||
|
||||
try |
||||
{ |
||||
Process.Start(new ProcessStartInfo { |
||||
FileName = path, |
||||
UseShellExecute = true, |
||||
}); |
||||
} |
||||
catch (Exception ex) |
||||
{ |
||||
Console.Error.WriteLine($"CaptureAndShow: failed to launch viewer for {path}: {ex.Message}"); |
||||
} |
||||
} |
||||
|
||||
static string Sanitize(string? label) |
||||
{ |
||||
if (string.IsNullOrWhiteSpace(label)) |
||||
return "frame"; |
||||
return new string(label.Select(c => char.IsLetterOrDigit(c) ? c : '_').ToArray()); |
||||
} |
||||
} |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
<Application xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
x:Class="ILSpy.App" |
||||
xmlns:local="using:ILSpy" |
||||
RequestedThemeVariant="Default"> |
||||
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> |
||||
|
||||
<Application.DataTemplates> |
||||
<local:ViewLocator/> |
||||
</Application.DataTemplates> |
||||
|
||||
<Application.Styles> |
||||
<FluentTheme /> |
||||
</Application.Styles> |
||||
</Application> |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2026 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 Avalonia; |
||||
using Avalonia.Controls.ApplicationLifetimes; |
||||
using Avalonia.Markup.Xaml; |
||||
|
||||
using ILSpy.ViewModels; |
||||
using ILSpy.Views; |
||||
|
||||
namespace ILSpy |
||||
{ |
||||
public partial class App : Application |
||||
{ |
||||
public override void Initialize() |
||||
{ |
||||
AvaloniaXamlLoader.Load(this); |
||||
} |
||||
|
||||
public override void OnFrameworkInitializationCompleted() |
||||
{ |
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) |
||||
{ |
||||
desktop.MainWindow = new MainWindow { |
||||
DataContext = new MainWindowViewModel(), |
||||
}; |
||||
} |
||||
|
||||
base.OnFrameworkInitializationCompleted(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) 2026 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.Runtime.CompilerServices; |
||||
|
||||
[assembly: InternalsVisibleTo("ILSpy.Tests")] |
||||
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk"> |
||||
<PropertyGroup> |
||||
<OutputType>WinExe</OutputType> |
||||
<TargetFramework>net10.0</TargetFramework> |
||||
<Nullable>enable</Nullable> |
||||
<ApplicationManifest>app.manifest</ApplicationManifest> |
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> |
||||
<RootNamespace>ICSharpCode.ILSpy</RootNamespace> |
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
</PropertyGroup> |
||||
|
||||
<ItemGroup> |
||||
<AvaloniaResource Include="Assets\**" /> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<AvaloniaResource Remove="Assets\ILSpy-Large.ico" /> |
||||
<AvaloniaResource Remove="Assets\ILSpy.pdn" /> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<!-- Avalonia core --> |
||||
<PackageReference Include="Avalonia" /> |
||||
<PackageReference Include="Avalonia.Desktop" /> |
||||
<PackageReference Include="Avalonia.Themes.Fluent" /> |
||||
<PackageReference Include="Avalonia.Fonts.Inter" /> |
||||
<PackageReference Include="AvaloniaUI.DiagnosticsSupport"> |
||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets> |
||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets> |
||||
</PackageReference> |
||||
|
||||
<!-- Editor, docking, grid, behaviors --> |
||||
<PackageReference Include="Avalonia.AvaloniaEdit" /> |
||||
<PackageReference Include="AvaloniaEdit.TextMate" /> |
||||
<PackageReference Include="Avalonia.Xaml.Behaviors" /> |
||||
<PackageReference Include="Dock.Avalonia" /> |
||||
<PackageReference Include="Dock.Model.Mvvm" /> |
||||
<PackageReference Include="ProDataGrid" /> |
||||
|
||||
<!-- MVVM, DI, MEF --> |
||||
<PackageReference Include="CommunityToolkit.Mvvm" /> |
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" /> |
||||
<PackageReference Include="System.Composition.AttributedModel" /> |
||||
|
||||
<!-- CLI parsing --> |
||||
<PackageReference Include="McMaster.Extensions.CommandLineUtils" /> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<ProjectReference Include="..\ICSharpCode.ILSpyX\ICSharpCode.ILSpyX.csproj" /> |
||||
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj" /> |
||||
</ItemGroup> |
||||
</Project> |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2026 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 Avalonia; |
||||
|
||||
namespace ILSpy |
||||
{ |
||||
sealed class Program |
||||
{ |
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
[STAThread] |
||||
public static void Main(string[] args) => BuildAvaloniaApp() |
||||
.StartWithClassicDesktopLifetime(args); |
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp() |
||||
=> AppBuilder.Configure<App>() |
||||
.UsePlatformDetect() |
||||
.WithInterFont() |
||||
.LogToTrace(); |
||||
} |
||||
} |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2026 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.CodeAnalysis; |
||||
|
||||
using Avalonia.Controls; |
||||
using Avalonia.Controls.Templates; |
||||
|
||||
using ILSpy.ViewModels; |
||||
|
||||
namespace ILSpy |
||||
{ |
||||
/// <summary>
|
||||
/// Given a view model, returns the corresponding view if possible.
|
||||
/// </summary>
|
||||
[RequiresUnreferencedCode( |
||||
"Default implementation of ViewLocator involves reflection which may be trimmed away.", |
||||
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")] |
||||
public class ViewLocator : IDataTemplate |
||||
{ |
||||
public Control? Build(object? param) |
||||
{ |
||||
if (param is null) |
||||
return null; |
||||
|
||||
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); |
||||
var type = Type.GetType(name); |
||||
|
||||
if (type != null) |
||||
{ |
||||
return (Control)Activator.CreateInstance(type)!; |
||||
} |
||||
|
||||
return new TextBlock { Text = "Not Found: " + name }; |
||||
} |
||||
|
||||
public bool Match(object? data) |
||||
{ |
||||
return data is ViewModelBase; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2026 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.
|
||||
|
||||
namespace ILSpy.ViewModels |
||||
{ |
||||
public partial class MainWindowViewModel : ViewModelBase |
||||
{ |
||||
public string Greeting { get; } = "Welcome to Avalonia!"; |
||||
} |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2026 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 CommunityToolkit.Mvvm.ComponentModel; |
||||
|
||||
namespace ILSpy.ViewModels |
||||
{ |
||||
public abstract class ViewModelBase : ObservableObject |
||||
{ |
||||
} |
||||
} |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||
x:Class="ILSpy.MainMenu"> |
||||
<Menu DockPanel.Dock="Top" Name="Menu" Height="23" KeyboardNavigation.TabNavigation="None"> |
||||
<MenuItem Header="_File" Tag="_File"> |
||||
<!-- content of file menu is added using MEF --> |
||||
</MenuItem> |
||||
</Menu> |
||||
</UserControl> |
||||
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2026 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 Avalonia; |
||||
using Avalonia.Controls; |
||||
using Avalonia.Markup.Xaml; |
||||
|
||||
namespace ILSpy; |
||||
|
||||
public partial class MainMenu : UserControl |
||||
{ |
||||
public MainMenu() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
<Window xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:vm="using:ILSpy.ViewModels" |
||||
xmlns:local="using:ILSpy" |
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||
x:Class="ILSpy.Views.MainWindow" |
||||
x:DataType="vm:MainWindowViewModel" |
||||
Icon="/Assets/ILSpy.ico" |
||||
Title="ILSpy"> |
||||
|
||||
<Design.DataContext> |
||||
<!-- This only sets the DataContext for the previewer in an IDE, |
||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) --> |
||||
<vm:MainWindowViewModel/> |
||||
</Design.DataContext> |
||||
|
||||
<DockPanel> |
||||
<local:MainMenu DockPanel.Dock="Top" /> |
||||
|
||||
</DockPanel> |
||||
|
||||
</Window> |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2026 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 Avalonia.Controls; |
||||
|
||||
namespace ILSpy.Views |
||||
{ |
||||
public partial class MainWindow : Window |
||||
{ |
||||
public MainWindow() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
||||
<!-- This manifest is used on Windows only. |
||||
Don't remove it as it might cause problems with window transparency and embedded controls. |
||||
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests --> |
||||
<assemblyIdentity version="1.0.0.0" name="ILSpy.Desktop"/> |
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> |
||||
<application> |
||||
<!-- A list of the Windows versions that this application has been tested on |
||||
and is designed to work with. Uncomment the appropriate elements |
||||
and Windows will automatically select the most compatible environment. --> |
||||
|
||||
<!-- Windows 10 --> |
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> |
||||
</application> |
||||
</compatibility> |
||||
</assembly> |
||||
Loading…
Reference in new issue