.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

95 lines
3.9 KiB

// 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.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Threading.Tasks;
using Avalonia.Headless.NUnit;
using AwesomeAssertions;
using ICSharpCode.Decompiler.TypeSystem;
using ILSpy;
using ILSpy.Commands;
using ILSpy.Metadata;
using ILSpy.TextView;
using NUnit.Framework;
namespace ICSharpCode.ILSpy.Tests.Metadata;
[TestFixture]
public class ShowInMetadataContextMenuTests
{
[AvaloniaTest]
public async Task Right_Click_On_An_Entity_Reference_In_The_Decompiler_Routes_To_Its_Metadata_Row()
{
// End-to-end: open a CoreLib type so the decompiler view fills with entity
// hyperlinks; synthesize a TextViewContext pointing at one of those references;
// verify the entry's IsVisible/Execute drives the dock workspace into the right
// metadata table for the entity's MetadataToken.kind.
var (_, vm) = await TestHarness.BootAsync();
var assemblyNode = vm.AssemblyTreeModel.FindCoreLib();
// Resolve System.Object's IEntity via the type system, since the entry only acts
// on IEntity-bearing references.
await assemblyNode.LoadedAssembly.GetLoadResultAsync();
var ts = assemblyNode.LoadedAssembly.GetTypeSystemOrNull()!;
var entity = ts.MainModule.TypeDefinitions.Single(t => t.FullName == "System.Object");
entity.MetadataToken.IsNil.Should().BeFalse(
"System.Object must have a real metadata token in CoreLib");
var ctx = new TextViewContext {
TextView = new DecompilerTextView(),
Reference = new ReferenceSegment { Reference = entity },
};
var entry = new ShowInMetadataContextMenuEntry();
entry.IsVisible(ctx).Should().BeTrue(
"the entry must surface for entity references in the decompiler view");
entry.Execute(ctx);
var expectedTable = (TableIndex)(int)entity.MetadataToken.Kind;
await Waiters.WaitForAsync(
() => vm.AssemblyTreeModel.SelectedItem is MetadataTableTreeNode m
&& m.Kind == expectedTable);
TestCapture.Step("show-in-metadata-table");
((MetadataTableTreeNode)vm.AssemblyTreeModel.SelectedItem!).Kind.Should().Be(expectedTable);
}
[AvaloniaTest]
public void IsVisible_False_When_There_Is_No_TextView_Or_Entity_Reference()
{
// The entry is decompiler-only. A right-click in a context that has no TextView,
// or whose Reference is null / not an IEntity (e.g. an opcode link), must not
// surface the entry — otherwise it would fire an unrelated NavigateToToken.
var entry = new ShowInMetadataContextMenuEntry();
entry.IsVisible(new TextViewContext()).Should().BeFalse();
entry.IsVisible(new TextViewContext { TextView = new DecompilerTextView() })
.Should().BeFalse("a TextView without a Reference is just empty whitespace");
entry.IsVisible(new TextViewContext {
TextView = new DecompilerTextView(),
Reference = new ReferenceSegment { Reference = "not-an-entity" },
}).Should().BeFalse();
}
}