From 4783fe1d34c8e4fdc246636be39240670a8c3c0e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 27 Jul 2026 07:12:57 +0200 Subject: [PATCH] Add VBPretty spec for VB.NET parameterized properties C# has no syntax for named properties with parameters, so the expected output declares the accessors as ordinary methods, keeps the property-level attributes under the inert 'property:' attribute target (ignored by csc with CS0657), and consumes the properties through direct accessor calls, which Roslyn permits exactly for properties whose shape C# cannot bind. Red against the current decompiler, which emits a parameterless property whose body references the vanished parameters. Assisted-by: Claude:claude-fable-5:Claude Code --- .../ICSharpCode.Decompiler.Tests.csproj | 1 + .../VBPretty/ParameterizedProperties.cs | 68 +++++++++++++++++++ .../VBPretty/ParameterizedProperties.vb | 53 +++++++++++++++ .../VBPrettyTestRunner.cs | 6 ++ 4 files changed, 128 insertions(+) create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.cs create mode 100644 ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.vb diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index d38245d46..4cdadca46 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -148,6 +148,7 @@ + diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.cs new file mode 100644 index 000000000..8f034867a --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.cs @@ -0,0 +1,68 @@ +#pragma warning disable 657 +using System; + +public interface IParameterized +{ + // C# has no syntax for parameterized properties; the accessors of + // property 'IndexedValue' are emitted as ordinary methods. + int get_IndexedValue(int index); + void set_IndexedValue(int index, int Value); +} + +public class ParameterizedProperties : IParameterized +{ + private int _field; + + // C# has no syntax for parameterized properties; the accessors of + // property 'SharedProp' are emitted as ordinary methods. + public static int get_SharedProp(int index) + { + return index; + } + + public static void set_SharedProp(int index, int value) + { + } + + // C# has no syntax for parameterized properties; the accessors of + // property 'IndexedValue' are emitted as ordinary methods. + public int get_IndexedValue(int index) + { + return _field; + } + + public void set_IndexedValue(int index, int value) + { + _field = value; + } + + // C# has no syntax for parameterized properties; the accessors of + // property 'ReadOnlyProp' are emitted as ordinary methods. + public int get_ReadOnlyProp(int index) + { + return index; + } + + // C# has no syntax for parameterized properties; the accessors of + // property 'Attributed' are emitted as ordinary methods. The property's + // attributes are kept below under the inert 'property:' target (CS0657). + [property: Obsolete("read-write parameterized property")] + public int get_Attributed(int index) + { + return index; + } + + public void set_Attributed(int index, int value) + { + } + + public void Use() + { + ParameterizedProperties.set_SharedProp(1, 2); + _field = ParameterizedProperties.get_SharedProp(3); + this.set_IndexedValue(4, 5); + _field = this.get_IndexedValue(6); + ((IParameterized)this).set_IndexedValue(7, 8); + _field = ((IParameterized)this).get_IndexedValue(9); + } +} diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.vb b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.vb new file mode 100644 index 000000000..eef450eb7 --- /dev/null +++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/ParameterizedProperties.vb @@ -0,0 +1,53 @@ +Imports System + +Public Interface IParameterized + Property IndexedValue(index As Integer) As Integer +End Interface + +Public Class ParameterizedProperties + Implements IParameterized + + Private _field As Integer + + Public Shared Property SharedProp(index As Integer) As Integer + Get + Return index + End Get + Set(value As Integer) + End Set + End Property + + Public Property IndexedValue(index As Integer) As Integer Implements IParameterized.IndexedValue + Get + Return _field + End Get + Set(value As Integer) + _field = value + End Set + End Property + + Public ReadOnly Property ReadOnlyProp(index As Integer) As Integer + Get + Return index + End Get + End Property + + + Public Property Attributed(index As Integer) As Integer + Get + Return index + End Get + Set(value As Integer) + End Set + End Property + + Public Sub Use() + SharedProp(1) = 2 + _field = SharedProp(3) + IndexedValue(4) = 5 + _field = IndexedValue(6) + Dim p As IParameterized = Me + p.IndexedValue(7) = 8 + _field = p.IndexedValue(9) + End Sub +End Class diff --git a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs index 08c556392..1aa52c90a 100644 --- a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs @@ -113,6 +113,12 @@ namespace ICSharpCode.Decompiler.Tests await Run(options: options | CompilerOptions.Library); } + [Test] + public async Task ParameterizedProperties([ValueSource(nameof(defaultOptions))] CompilerOptions options) + { + await Run(options: options | CompilerOptions.Library); + } + [Test] public async Task Select([ValueSource(nameof(defaultOptions))] CompilerOptions options) {