Browse Source

Handle explicit optional parameter after default parameter

pull/3470/head
ds5678 2 months ago committed by Jeremy Pritts
parent
commit
2a0675fb4a
  1. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
  2. 3
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  3. 30
      ICSharpCode.Decompiler/TypeSystem/IParameter.cs
  4. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs

@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -307,6 +308,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
} }
#endif #endif
public static void Issue3469([Optional][DefaultParameterValue(0)] int i, [Optional] DateTime d)
{
}
#if CS120 #if CS120
public static D LambdaWithOptionalParameter() public static D LambdaWithOptionalParameter()

3
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -1735,8 +1735,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
decl.Name = parameter.Name; decl.Name = parameter.Name;
} }
if (parameter.IsOptional && decl.ParameterModifier is ReferenceKind.None or ReferenceKind.In or ReferenceKind.RefReadOnly if (parameter.GetDefaultValueAssignmentAllowed() && this.ShowConstantValues)
&& parameter.HasConstantValueInSignature && this.ShowConstantValues)
{ {
try try
{ {

30
ICSharpCode.Decompiler/TypeSystem/IParameter.cs

@ -105,4 +105,34 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
IParameterizedMember? Owner { get; } IParameterizedMember? Owner { get; }
} }
internal static class IParameterExtensions
{
public static bool GetDefaultValueAssignmentAllowed(this IParameter parameter)
{
if (!DefaultValueAssignmentAllowedIndividual(parameter))
return false;
if (parameter.Owner == null)
return true;
for (int i = parameter.Owner.Parameters.Count - 1; i >= 0; i--)
{
IParameter otherParameter = parameter.Owner.Parameters[i];
if (otherParameter == parameter)
break;
if (DefaultValueAssignmentAllowedIndividual(otherParameter) || otherParameter.IsParams)
continue;
return false;
}
return true;
static bool DefaultValueAssignmentAllowedIndividual(IParameter parameter)
{
return parameter.IsOptional && parameter.HasConstantValueInSignature && parameter.ReferenceKind is ReferenceKind.None or ReferenceKind.In or ReferenceKind.RefReadOnly;
}
}
}
} }

6
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs

@ -63,14 +63,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var metadata = module.metadata; var metadata = module.metadata;
var parameter = metadata.GetParameter(handle); var parameter = metadata.GetParameter(handle);
bool defaultValueAssignmentAllowed = ReferenceKind is ReferenceKind.None or ReferenceKind.In or ReferenceKind.RefReadOnly; bool defaultValueAssignmentAllowed = this.GetDefaultValueAssignmentAllowed();
if (IsOptional && (!defaultValueAssignmentAllowed || !HasConstantValueInSignature)) if (IsOptional && !defaultValueAssignmentAllowed)
{ {
b.Add(KnownAttribute.Optional); b.Add(KnownAttribute.Optional);
} }
if (!(IsDecimalConstant || !HasConstantValueInSignature) && (!defaultValueAssignmentAllowed || !IsOptional)) if (!IsDecimalConstant && HasConstantValueInSignature && !defaultValueAssignmentAllowed)
{ {
b.Add(KnownAttribute.DefaultParameterValue, KnownTypeCode.Object, GetConstantValue(throwOnInvalidMetadata: false)); b.Add(KnownAttribute.DefaultParameterValue, KnownTypeCode.Object, GetConstantValue(throwOnInvalidMetadata: false));
} }

Loading…
Cancel
Save