diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..eec8dbd5f --- /dev/null +++ b/CLAUDE.md @@ -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: ` 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. diff --git a/Directory.Packages.props b/Directory.Packages.props index f96b737b0..d30c70dd6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,9 +7,28 @@ 5.7.0-1.26230.115 10.0.8 2.24.0 + 12.0.1 + 12.0.0.1 + + + + + + + + + + + + + + + + + diff --git a/ILSpy.Tests/AppInitializationTests.cs b/ILSpy.Tests/AppInitializationTests.cs new file mode 100644 index 000000000..0ea901b03 --- /dev/null +++ b/ILSpy.Tests/AppInitializationTests.cs @@ -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."); + } +} diff --git a/ILSpy.Tests/ILSpy.Tests.csproj b/ILSpy.Tests/ILSpy.Tests.csproj new file mode 100644 index 000000000..58b954648 --- /dev/null +++ b/ILSpy.Tests/ILSpy.Tests.csproj @@ -0,0 +1,28 @@ + + + + net11.0 + Exe + enable + false + ICSharpCode.ILSpy.Tests + true + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy.Tests/TestApp.axaml b/ILSpy.Tests/TestApp.axaml new file mode 100644 index 000000000..42b0b3b43 --- /dev/null +++ b/ILSpy.Tests/TestApp.axaml @@ -0,0 +1,4 @@ + diff --git a/ILSpy.Tests/TestApp.axaml.cs b/ILSpy.Tests/TestApp.axaml.cs new file mode 100644 index 000000000..1d915732c --- /dev/null +++ b/ILSpy.Tests/TestApp.axaml.cs @@ -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; + } +} diff --git a/ILSpy.Tests/TestAppBuilder.cs b/ILSpy.Tests/TestAppBuilder.cs new file mode 100644 index 000000000..85273937b --- /dev/null +++ b/ILSpy.Tests/TestAppBuilder.cs @@ -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() + .UseSkia() + .UseHeadless(new AvaloniaHeadlessPlatformOptions { + UseHeadlessDrawing = !visible, + }); + } +} diff --git a/ILSpy.Tests/WindowExtensions.cs b/ILSpy.Tests/WindowExtensions.cs new file mode 100644 index 000000000..8ebd2480e --- /dev/null +++ b/ILSpy.Tests/WindowExtensions.cs @@ -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 +{ + /// Snapshots the window with Skia, writes a temp PNG, and opens it in the OS + /// image viewer. No-op when UseHeadlessDrawing is true (CI default). + 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()); + } +} diff --git a/ILSpy.sln b/ILSpy.sln index 7b24b46b1..06ff2bb8a 100644 --- a/ILSpy.sln +++ b/ILSpy.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 VisualStudioVersion = 18.4.11620.152 @@ -33,40 +32,128 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution NuGet.config = NuGet.config EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{2C085978-F6EC-4684-B987-802D4CFEC3E9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy.Tests", "ILSpy.Tests\ILSpy.Tests.csproj", "{818CA2D4-175F-4DC1-9C83-189D2CA74ABA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {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}.Debug|x64.ActiveCfg = Debug|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x64.Build.0 = Debug|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.ActiveCfg = Debug|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Debug|x86.Build.0 = Debug|Any CPU {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.ActiveCfg = Release|Any CPU {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|Any CPU.Build.0 = Release|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x64.ActiveCfg = Release|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x64.Build.0 = Release|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.ActiveCfg = Release|Any CPU + {984CC812-9470-4A13-AFF9-CC44068D666C}.Release|x86.Build.0 = Release|Any CPU {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x64.ActiveCfg = Debug|Any CPU + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x64.Build.0 = Debug|Any CPU + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x86.ActiveCfg = Debug|Any CPU + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Debug|x86.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 + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x64.ActiveCfg = Release|Any CPU + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x64.Build.0 = Release|Any CPU + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.ActiveCfg = Release|Any CPU + {FEC0DA52-C4A6-4710-BE36-B484A20C5E22}.Release|x86.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}.Debug|x64.ActiveCfg = Debug|Any CPU + {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Debug|x64.Build.0 = Debug|Any CPU + {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Debug|x86.ActiveCfg = Debug|Any CPU + {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Debug|x86.Build.0 = Debug|Any CPU {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Release|Any CPU.ActiveCfg = Release|Any CPU {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Release|Any CPU.Build.0 = Release|Any CPU + {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Release|x64.ActiveCfg = Release|Any CPU + {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Release|x64.Build.0 = Release|Any CPU + {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Release|x86.ActiveCfg = Release|Any CPU + {743B439A-E7AD-4A0A-BAB6-222E1EA83C6D}.Release|x86.Build.0 = Release|Any CPU {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Debug|x64.ActiveCfg = Debug|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Debug|x64.Build.0 = Debug|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Debug|x86.ActiveCfg = Debug|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Debug|x86.Build.0 = Debug|Any CPU {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Release|Any CPU.Build.0 = Release|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Release|x64.ActiveCfg = Release|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Release|x64.Build.0 = Release|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Release|x86.ActiveCfg = Release|Any CPU + {50060E0C-FA25-41F4-B72F-8490324EC9F0}.Release|x86.Build.0 = Release|Any CPU {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|x64.ActiveCfg = Debug|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|x64.Build.0 = Debug|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|x86.ActiveCfg = Debug|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|x86.Build.0 = Debug|Any CPU {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|Any CPU.Build.0 = Release|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|x64.ActiveCfg = Release|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|x64.Build.0 = Release|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|x86.ActiveCfg = Release|Any CPU + {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|x86.Build.0 = Release|Any CPU {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|x64.ActiveCfg = Debug|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|x64.Build.0 = Debug|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|x86.ActiveCfg = Debug|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|x86.Build.0 = Debug|Any CPU {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|Any CPU.ActiveCfg = Release|Any CPU {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|Any CPU.Build.0 = Release|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|x64.ActiveCfg = Release|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|x64.Build.0 = Release|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|x86.ActiveCfg = Release|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|x86.Build.0 = Release|Any CPU {81A30182-3378-4952-8880-F44822390040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {81A30182-3378-4952-8880-F44822390040}.Debug|Any CPU.Build.0 = Debug|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Debug|x64.ActiveCfg = Debug|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Debug|x64.Build.0 = Debug|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Debug|x86.ActiveCfg = Debug|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Debug|x86.Build.0 = Debug|Any CPU {81A30182-3378-4952-8880-F44822390040}.Release|Any CPU.ActiveCfg = Release|Any CPU {81A30182-3378-4952-8880-F44822390040}.Release|Any CPU.Build.0 = Release|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Release|x64.ActiveCfg = Release|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Release|x64.Build.0 = Release|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Release|x86.ActiveCfg = Release|Any CPU + {81A30182-3378-4952-8880-F44822390040}.Release|x86.Build.0 = Release|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Debug|x64.ActiveCfg = Debug|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Debug|x64.Build.0 = Debug|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Debug|x86.ActiveCfg = Debug|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Debug|x86.Build.0 = Debug|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Release|Any CPU.Build.0 = Release|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Release|x64.ActiveCfg = Release|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Release|x64.Build.0 = Release|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Release|x86.ActiveCfg = Release|Any CPU + {2C085978-F6EC-4684-B987-802D4CFEC3E9}.Release|x86.Build.0 = Release|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Debug|x64.ActiveCfg = Debug|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Debug|x64.Build.0 = Debug|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Debug|x86.ActiveCfg = Debug|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Debug|x86.Build.0 = Debug|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Release|Any CPU.Build.0 = Release|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Release|x64.ActiveCfg = Release|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Release|x64.Build.0 = Release|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Release|x86.ActiveCfg = Release|Any CPU + {818CA2D4-175F-4DC1-9C83-189D2CA74ABA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ILSpy/App.axaml b/ILSpy/App.axaml new file mode 100644 index 000000000..dd927346e --- /dev/null +++ b/ILSpy/App.axaml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/ILSpy/App.axaml.cs b/ILSpy/App.axaml.cs new file mode 100644 index 000000000..c8caa5277 --- /dev/null +++ b/ILSpy/App.axaml.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/ILSpy/AssemblyInfo.cs b/ILSpy/AssemblyInfo.cs new file mode 100644 index 000000000..22a4a426e --- /dev/null +++ b/ILSpy/AssemblyInfo.cs @@ -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")] diff --git a/ILSpy/Assets/ILSpy-Large.ico b/ILSpy/Assets/ILSpy-Large.ico new file mode 100644 index 000000000..14a26f95a Binary files /dev/null and b/ILSpy/Assets/ILSpy-Large.ico differ diff --git a/ILSpy/Assets/ILSpy.ico b/ILSpy/Assets/ILSpy.ico new file mode 100644 index 000000000..900abec81 Binary files /dev/null and b/ILSpy/Assets/ILSpy.ico differ diff --git a/ILSpy/Assets/ILSpy.pdn b/ILSpy/Assets/ILSpy.pdn new file mode 100644 index 000000000..c3ff16879 Binary files /dev/null and b/ILSpy/Assets/ILSpy.pdn differ diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj new file mode 100644 index 000000000..1dbd5c95c --- /dev/null +++ b/ILSpy/ILSpy.csproj @@ -0,0 +1,53 @@ + + + WinExe + net10.0 + enable + app.manifest + true + ICSharpCode.ILSpy + true + + + + + + + + + + + + + + + + + + + None + All + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Program.cs b/ILSpy/Program.cs new file mode 100644 index 000000000..8f73ace22 --- /dev/null +++ b/ILSpy/Program.cs @@ -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() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace(); + } +} \ No newline at end of file diff --git a/ILSpy/ViewLocator.cs b/ILSpy/ViewLocator.cs new file mode 100644 index 000000000..fdc171a95 --- /dev/null +++ b/ILSpy/ViewLocator.cs @@ -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 +{ + /// + /// Given a view model, returns the corresponding view if possible. + /// + [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; + } + } +} \ No newline at end of file diff --git a/ILSpy/ViewModels/MainWindowViewModel.cs b/ILSpy/ViewModels/MainWindowViewModel.cs new file mode 100644 index 000000000..ada082756 --- /dev/null +++ b/ILSpy/ViewModels/MainWindowViewModel.cs @@ -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!"; + } +} \ No newline at end of file diff --git a/ILSpy/ViewModels/ViewModelBase.cs b/ILSpy/ViewModels/ViewModelBase.cs new file mode 100644 index 000000000..818c83d18 --- /dev/null +++ b/ILSpy/ViewModels/ViewModelBase.cs @@ -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 + { + } +} \ No newline at end of file diff --git a/ILSpy/Views/MainMenu.axaml b/ILSpy/Views/MainMenu.axaml new file mode 100644 index 000000000..dbe938324 --- /dev/null +++ b/ILSpy/Views/MainMenu.axaml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/ILSpy/Views/MainMenu.axaml.cs b/ILSpy/Views/MainMenu.axaml.cs new file mode 100644 index 000000000..b68e479c5 --- /dev/null +++ b/ILSpy/Views/MainMenu.axaml.cs @@ -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(); + } +} \ No newline at end of file diff --git a/ILSpy/Views/MainWindow.axaml b/ILSpy/Views/MainWindow.axaml new file mode 100644 index 000000000..68dd5b91b --- /dev/null +++ b/ILSpy/Views/MainWindow.axaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + diff --git a/ILSpy/Views/MainWindow.axaml.cs b/ILSpy/Views/MainWindow.axaml.cs new file mode 100644 index 000000000..54d92925c --- /dev/null +++ b/ILSpy/Views/MainWindow.axaml.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/ILSpy/app.manifest b/ILSpy/app.manifest new file mode 100644 index 000000000..002108dcb --- /dev/null +++ b/ILSpy/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + +