Skip to content

Commit 586c04d

Browse files
ds5678siegfriedpammer
authored andcommitted
Support params keyword on non-array collections
1 parent 3449058 commit 586c04d

File tree

15 files changed

+105
-7
lines changed

15 files changed

+105
-7
lines changed

ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ public static List<string> GetPreprocessorSymbols(CompilerOptions flags)
459459
preprocessorSymbols.Add("CS100");
460460
preprocessorSymbols.Add("CS110");
461461
preprocessorSymbols.Add("CS120");
462+
preprocessorSymbols.Add("CS130");
462463
}
463464
}
464465
else if ((flags & CompilerOptions.UseMcsMask) != 0)
@@ -705,7 +706,7 @@ internal static DecompilerSettings GetSettings(CompilerOptions cscOptions)
705706
CompilerOptions.UseRoslyn1_3_2 => CSharp.LanguageVersion.CSharp6,
706707
CompilerOptions.UseRoslyn2_10_0 => CSharp.LanguageVersion.CSharp7_3,
707708
CompilerOptions.UseRoslyn3_11_0 => CSharp.LanguageVersion.CSharp9_0,
708-
_ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp12_0,
709+
_ => cscOptions.HasFlag(CompilerOptions.Preview) ? CSharp.LanguageVersion.Latest : CSharp.LanguageVersion.CSharp13_0,
709710
};
710711
DecompilerSettings settings = new(langVersion) {
711712
// Never use file-scoped namespaces

ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
<PropertyGroup>
1010
<TargetFramework>net10.0-windows</TargetFramework>
11+
<LangVersion>13</LangVersion>
1112
<RuntimeIdentifier Condition="$(IsWindowsX64) == true">win-x64</RuntimeIdentifier>
1213
<RuntimeIdentifier Condition="$(IsWindowsARM64) == true">win-arm64</RuntimeIdentifier>
1314

@@ -17,7 +18,7 @@
1718
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
1819

1920
<NoWarn>1701;1702;1705,67,169,1058,728,1720,649,168,251,660,661,675;1998;162;8632;626;8618;8714;8602;8981</NoWarn>
20-
<DefineConstants>ROSLYN;ROSLYN2;ROSLYN3;ROSLYN4;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100;CS110;CS120</DefineConstants>
21+
<DefineConstants>ROSLYN;ROSLYN2;ROSLYN3;ROSLYN4;NET60;CS60;CS70;CS71;CS72;CS73;CS80;CS90;CS100;CS110;CS120;CS130</DefineConstants>
2122

2223
<GenerateAssemblyVersionAttribute>False</GenerateAssemblyVersionAttribute>
2324
<GenerateAssemblyFileVersionAttribute>False</GenerateAssemblyFileVersionAttribute>
@@ -146,6 +147,7 @@
146147
<Compile Include="TestCases\Pretty\Issue3442.cs" />
147148
<Compile Include="TestCases\Pretty\Issue3483.cs" />
148149
<Compile Include="TestCases\Pretty\PointerArithmetic.cs" />
150+
<Compile Include="TestCases\Pretty\ParamsCollections.cs" />
149151
<None Include="TestCases\VBPretty\VBAutomaticEvents.vb" />
150152
<Compile Include="TestCases\VBPretty\VBAutomaticEvents.cs" />
151153
<Compile Include="TestCases\VBPretty\VBNonGenericForEach.cs" />

ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,12 @@ public async Task ConstantsTests([ValueSource(nameof(defaultOptions))] CompilerO
605605
await RunForLibrary(cscOptions: cscOptions);
606606
}
607607

608+
[Test]
609+
public async Task ParamsCollections([ValueSource(nameof(roslyn4OrNewerOptions))] CompilerOptions cscOptions)
610+
{
611+
await RunForLibrary(cscOptions: cscOptions);
612+
}
613+
608614
[Test]
609615
public async Task Issue1080([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions cscOptions)
610616
{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
5+
{
6+
public static class ParamsCollections
7+
{
8+
public static void ParamsEnumerable(params IEnumerable<int> values)
9+
{
10+
}
11+
public static void ParamsList(params List<int> values)
12+
{
13+
}
14+
public static void ParamsReadOnlySpan(params ReadOnlySpan<int> values)
15+
{
16+
}
17+
public static void ParamsSpan(params Span<int> values)
18+
{
19+
}
20+
}
21+
}

ICSharpCode.Decompiler/CSharp/CSharpLanguageVersion.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public enum LanguageVersion
3535
CSharp10_0 = 1000,
3636
CSharp11_0 = 1100,
3737
CSharp12_0 = 1200,
38-
Preview = 1100,
38+
CSharp13_0 = 1300,
39+
Preview = 1300,
3940
Latest = 0x7FFFFFFF
4041
}
4142
}

ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ public class RemoveEmbeddedAttributes : DepthFirstAstVisitor, IAstTransform
166166
"System.Runtime.CompilerServices.NullableAttribute",
167167
"System.Runtime.CompilerServices.NullableContextAttribute",
168168
"System.Runtime.CompilerServices.NativeIntegerAttribute",
169+
"System.Runtime.CompilerServices.ParamCollectionAttribute",
169170
"System.Runtime.CompilerServices.RefSafetyRulesAttribute",
170171
"System.Runtime.CompilerServices.ScopedRefAttribute",
171172
"System.Runtime.CompilerServices.RequiresLocationAttribute",

ICSharpCode.Decompiler/DecompilerSettings.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,16 @@ public void SetLanguageVersion(CSharp.LanguageVersion languageVersion)
166166
usePrimaryConstructorSyntaxForNonRecordTypes = false;
167167
inlineArrays = false;
168168
}
169+
if (languageVersion < CSharp.LanguageVersion.CSharp13_0)
170+
{
171+
paramsCollections = false;
172+
}
169173
}
170174

171175
public CSharp.LanguageVersion GetMinimumRequiredVersion()
172176
{
177+
if (paramsCollections)
178+
return CSharp.LanguageVersion.CSharp13_0;
173179
if (refReadOnlyParameters || usePrimaryConstructorSyntaxForNonRecordTypes || inlineArrays)
174180
return CSharp.LanguageVersion.CSharp12_0;
175181
if (scopedRef || requiredMembers || numericIntPtr || utf8StringLiterals || unsignedRightShift || checkedOperators)
@@ -849,6 +855,24 @@ public bool ForEachWithGetEnumeratorExtension {
849855
}
850856
}
851857

858+
bool paramsCollections = true;
859+
860+
/// <summary>
861+
/// Support params collections.
862+
/// </summary>
863+
[Category("C# 13.0 / VS 2022.12")]
864+
[Description("DecompilerSettings.DecompileParamsCollections")]
865+
public bool ParamsCollections {
866+
get { return paramsCollections; }
867+
set {
868+
if (paramsCollections != value)
869+
{
870+
paramsCollections = value;
871+
OnPropertyChanged();
872+
}
873+
}
874+
}
875+
852876
bool lockStatement = true;
853877

854878
/// <summary>

ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,19 @@ public enum TypeSystemOptions
138138
/// </summary>
139139
RefReadOnlyParameters = 0x10000,
140140
/// <summary>
141+
/// If this option is active, [ParamCollectionAttribute] on parameters is removed
142+
/// and parameters are marked as params.
143+
/// Otherwise, the attribute is preserved but the parameters are not marked
144+
/// as if it was a normal parameter without any attributes.
145+
/// </summary>
146+
ParamsCollections = 0x20000,
147+
/// <summary>
141148
/// Default settings: typical options for the decompiler, with all C# languages features enabled.
142149
/// </summary>
143150
Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants | ReadOnlyStructsAndParameters
144151
| RefStructs | UnmanagedConstraints | NullabilityAnnotations | ReadOnlyMethods
145152
| NativeIntegers | FunctionPointers | ScopedRef | NativeIntegersWithoutAttribute
146-
| RefReadOnlyParameters
153+
| RefReadOnlyParameters | ParamsCollections
147154
}
148155

149156
/// <summary>
@@ -185,6 +192,8 @@ public static TypeSystemOptions GetOptions(DecompilerSettings settings)
185192
typeSystemOptions |= TypeSystemOptions.NativeIntegersWithoutAttribute;
186193
if (settings.RefReadOnlyParameters)
187194
typeSystemOptions |= TypeSystemOptions.RefReadOnlyParameters;
195+
if (settings.ParamsCollections)
196+
typeSystemOptions |= TypeSystemOptions.ParamsCollections;
188197
return typeSystemOptions;
189198
}
190199

ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ internal bool IgnoreAttribute(TopLevelTypeName attributeType, SymbolKind target)
258258
case "RequiresLocationAttribute":
259259
return (options & TypeSystemOptions.RefReadOnlyParameters) != 0
260260
&& (target == SymbolKind.Parameter);
261+
case "ParamCollectionAttribute":
262+
return (options & TypeSystemOptions.ParamsCollections) != 0
263+
&& (target == SymbolKind.Parameter);
261264
default:
262265
return false;
263266
}

ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public enum KnownAttribute
8787

8888
// Parameter attributes:
8989
ParamArray,
90+
ParamCollection,
9091
In,
9192
Out,
9293
Optional,
@@ -169,6 +170,7 @@ public static class KnownAttributes
169170
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(IndexerNameAttribute)),
170171
// Parameter attributes:
171172
new TopLevelTypeName("System", nameof(ParamArrayAttribute)),
173+
new TopLevelTypeName("System.Runtime.CompilerServices", "ParamCollectionAttribute"),
172174
new TopLevelTypeName("System.Runtime.InteropServices", nameof(InAttribute)),
173175
new TopLevelTypeName("System.Runtime.InteropServices", nameof(OutAttribute)),
174176
new TopLevelTypeName("System.Runtime.InteropServices", nameof(OptionalAttribute)),

0 commit comments

Comments
 (0)