mirror of https://github.com/icsharpcode/ILSpy.git
35 changed files with 792 additions and 227 deletions
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||
{ |
||||
internal static class EmptyGroups |
||||
{ |
||||
extension(int) |
||||
{ |
||||
} |
||||
|
||||
extension(int x) |
||||
{ |
||||
} |
||||
|
||||
extension(int y) |
||||
{ |
||||
} |
||||
|
||||
extension<T>(IEnumerable<T>) |
||||
{ |
||||
} |
||||
|
||||
extension<T>(IEnumerable<T> x) |
||||
{ |
||||
} |
||||
|
||||
extension<T>(IEnumerable<T> y) |
||||
{ |
||||
} |
||||
|
||||
extension<TKey, TValue>(Dictionary<TKey, TValue>) |
||||
{ |
||||
} |
||||
|
||||
extension<TKey, TValue>(Dictionary<TKey, TValue> x) |
||||
{ |
||||
} |
||||
|
||||
extension<TKey, TValue>(Dictionary<TKey, TValue> y) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
internal static class ExtensionEverything |
||||
{ |
||||
extension<T>(ICollection<T> collection) where T : notnull |
||||
{ |
||||
public bool IsEmpty => collection.Count == 0; |
||||
|
||||
public int Test { |
||||
get { |
||||
return 42; |
||||
} |
||||
set { |
||||
} |
||||
} |
||||
|
||||
public void AddIfNotNull(T item) |
||||
{ |
||||
if (item != null) |
||||
{ |
||||
collection.Add(item); |
||||
} |
||||
} |
||||
|
||||
public T2 CastElementAt<T2>(int index) where T2 : T |
||||
{ |
||||
return (T2)(object)collection.ElementAt(index); |
||||
} |
||||
|
||||
public static void StaticExtension() |
||||
{ |
||||
} |
||||
} |
||||
|
||||
extension(ExtensionEverythingTestUseSites.Point point) |
||||
{ |
||||
public double Magnitude => Math.Sqrt(point.X * point.X + point.Y * point.Y); |
||||
} |
||||
} |
||||
|
||||
internal class ExtensionEverythingTestUseSites |
||||
{ |
||||
public record struct Point(int X, int Y); |
||||
|
||||
public static void TestExtensionProperty() |
||||
{ |
||||
Point point = new Point(3, 4); |
||||
Console.WriteLine(point.X); |
||||
Console.WriteLine(point.Y); |
||||
// TODO implement use-site transformation
|
||||
//Console.WriteLine(point.Magnitude);
|
||||
} |
||||
|
||||
public static void TestExtensionMethods() |
||||
{ |
||||
List<string> collection = new List<string>(); |
||||
// TODO implement use-site transformation
|
||||
//Console.WriteLine(collection.IsEmpty);
|
||||
collection.AddIfNotNull("Hello"); |
||||
collection.AddIfNotNull(null); |
||||
//Console.WriteLine(collection.IsEmpty);
|
||||
//Console.WriteLine(collection.Test);
|
||||
//collection.Test = 100;
|
||||
//List<string>.StaticExtension();
|
||||
} |
||||
} |
||||
} |
||||
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||
{ |
||||
internal static class ExtensionProperties |
||||
{ |
||||
extension<T>(ICollection<T> collection) where T : notnull |
||||
{ |
||||
public bool IsEmpty => collection.Count == 0; |
||||
|
||||
public int Test { |
||||
get { |
||||
return 42; |
||||
} |
||||
set { |
||||
} |
||||
} |
||||
|
||||
public void AddIfNotNull(T item) |
||||
{ |
||||
if (item != null) |
||||
{ |
||||
collection.Add(item); |
||||
} |
||||
} |
||||
|
||||
public T2 Cast<T2>(int index) where T2 : T |
||||
{ |
||||
return (T2)(object)collection.ElementAt(index); |
||||
} |
||||
|
||||
public static void StaticExtension() |
||||
{ |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
<DrawingGroup xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
||||
<DrawingGroup.Children> |
||||
<GeometryDrawing Geometry="F1 M16,16z M0,0z M16,16L0,16 0,0 16,0z"> |
||||
<GeometryDrawing.Brush> |
||||
<SolidColorBrush Color="#FFF6F6F6" Opacity="0" /> |
||||
</GeometryDrawing.Brush> |
||||
</GeometryDrawing> |
||||
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1 M16,16z M0,0z M14.47,9.056L14,9.525 14,5 10,5 10,9.525 9.53,9.055 8,10.586 8,12.475 11.525,16 12.474,16 16,12.475 16,10.586z" /> |
||||
<GeometryDrawing Brush="#FF424242" Geometry="F1 M16,16z M0,0z M13,9L11,9 11,8 13,8z M13,6L11,6 11,7 13,7z M14.47,10.47L13,11.939 13,10 11,10 11,11.939 9.53,10.469 8.47,11.53 12,15.06 15.53,11.53z" /> |
||||
</DrawingGroup.Children> |
||||
</DrawingGroup> |
||||
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2026 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 ICSharpCode.Decompiler; |
||||
|
||||
using SRM = System.Reflection.Metadata; |
||||
|
||||
namespace ICSharpCode.ILSpy.TreeNodes |
||||
{ |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
|
||||
using ICSharpCode.Decompiler.Output; |
||||
using ICSharpCode.Decompiler.TypeSystem; |
||||
|
||||
public sealed class ExtensionTreeNode : ILSpyTreeNode |
||||
{ |
||||
public ExtensionTreeNode(ITypeDefinition typeDefinition, (IMethod Marker, IReadOnlyList<ITypeParameter> TypeParameters) extensionGroup, AssemblyTreeNode parentAssemblyNode) |
||||
{ |
||||
this.ParentAssemblyNode = parentAssemblyNode ?? throw new ArgumentNullException(nameof(parentAssemblyNode)); |
||||
this.ContainerTypeDefinition = typeDefinition ?? throw new ArgumentNullException(nameof(typeDefinition)); |
||||
this.MarkerMethod = extensionGroup.Marker ?? throw new ArgumentNullException(nameof(extensionGroup.Marker)); |
||||
this.TypeParameters = extensionGroup.TypeParameters ?? throw new ArgumentNullException(nameof(extensionGroup.TypeParameters)); |
||||
this.LazyLoading = true; |
||||
} |
||||
|
||||
public ITypeDefinition ContainerTypeDefinition { get; } |
||||
|
||||
public IMethod MarkerMethod { get; } |
||||
|
||||
public IReadOnlyList<ITypeParameter> TypeParameters { get; } |
||||
|
||||
public AssemblyTreeNode ParentAssemblyNode { get; } |
||||
|
||||
public override object Icon => Images.GetIcon(TypeIcon.Class, AccessOverlayIcon.Public, false, true); |
||||
|
||||
public override object Text => this.Language.TypeToString(GetTypeDefinition(), ConversionFlags.SupportExtensionDeclarations); |
||||
|
||||
public override object NavigationText => this.Language.TypeToString(GetTypeDefinition(), ConversionFlags.UseFullyQualifiedTypeNames | ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.SupportExtensionDeclarations); |
||||
|
||||
private ITypeDefinition GetTypeDefinition() |
||||
{ |
||||
return ((MetadataModule)ParentAssemblyNode.LoadedAssembly |
||||
.GetMetadataFileOrNull() |
||||
?.GetTypeSystemWithCurrentOptionsOrNull(SettingsService, AssemblyTreeModel.CurrentLanguageVersion) |
||||
?.MainModule)?.GetDefinition((SRM.TypeDefinitionHandle)MarkerMethod.DeclaringTypeDefinition.MetadataToken) |
||||
?? MarkerMethod.DeclaringTypeDefinition; |
||||
} |
||||
|
||||
protected override void LoadChildren() |
||||
{ |
||||
var extensionInfo = ContainerTypeDefinition.ExtensionInfo; |
||||
var members = extensionInfo.GetMembersOfGroup(MarkerMethod).ToList(); |
||||
|
||||
foreach (var property in members.OfType<IProperty>().OrderBy(p => p.Name, NaturalStringComparer.Instance)) |
||||
{ |
||||
this.Children.Add(new PropertyTreeNode(property)); |
||||
} |
||||
foreach (var method in members.OfType<IMethod>().OrderBy(m => m.Name, NaturalStringComparer.Instance)) |
||||
{ |
||||
if (method.MetadataToken.IsNil) |
||||
continue; |
||||
this.Children.Add(new MethodTreeNode(method)); |
||||
} |
||||
} |
||||
|
||||
public override FilterResult Filter(LanguageSettings settings) |
||||
{ |
||||
if (LanguageService.Language is not CSharpLanguage) |
||||
return FilterResult.Hidden; |
||||
|
||||
var decompilerSettings = SettingsService.DecompilerSettings.Clone(); |
||||
if (!Enum.TryParse(AssemblyTreeModel.CurrentLanguageVersion?.Version, out Decompiler.CSharp.LanguageVersion languageVersion)) |
||||
languageVersion = Decompiler.CSharp.LanguageVersion.Latest; |
||||
decompilerSettings.SetLanguageVersion(languageVersion); |
||||
|
||||
if (!decompilerSettings.ExtensionMembers) |
||||
return FilterResult.Hidden; |
||||
|
||||
return base.Filter(settings); |
||||
} |
||||
|
||||
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) |
||||
{ |
||||
Debug.Assert(language is CSharpLanguage); |
||||
((CSharpLanguage)language).DecompileExtension(GetTypeDefinition(), output, options); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue