Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -307,8 +308,17 @@ public static void Issue2920p(in int x = 3)
{
}
#endif

public static void Issue3469a([Optional][DefaultParameterValue(0)] int i, [Optional] DateTime d)
{
}
#if CS120
public static Action<int, DateTime> Issue3469b()
{
Comment thread
ds5678 marked this conversation as resolved.
#pragma warning disable CS9099 // Parameter 1 has default value 'default(int)' in lambda but '<missing>' in the target delegate type
return ([Optional][DefaultParameterValue(0)] int i, [Optional] DateTime d) => {
};
Comment thread
ds5678 marked this conversation as resolved.
#pragma warning restore CS9099
}
public static D LambdaWithOptionalParameter()
{
return (int x = 10) => x;
Expand Down
3 changes: 1 addition & 2 deletions ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1735,8 +1735,7 @@ public ParameterDeclaration ConvertParameter(IParameter parameter)
{
decl.Name = parameter.Name;
}
if (parameter.IsOptional && decl.ParameterModifier is ReferenceKind.None or ReferenceKind.In or ReferenceKind.RefReadOnly
&& parameter.HasConstantValueInSignature && this.ShowConstantValues)
if (parameter.IsDefaultValueAssignmentAllowed() && this.ShowConstantValues)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ public IEnumerable<IAttribute> GetAttributes()
var metadata = module.metadata;
var parameter = metadata.GetParameter(handle);

bool defaultValueAssignmentAllowed = ReferenceKind is ReferenceKind.None or ReferenceKind.In or ReferenceKind.RefReadOnly;
bool defaultValueAssignmentAllowed = this.IsDefaultValueAssignmentAllowed();

if (IsOptional && (!defaultValueAssignmentAllowed || !HasConstantValueInSignature))
if (IsOptional && !defaultValueAssignmentAllowed)
{
b.Add(KnownAttribute.Optional);
}

if (!(IsDecimalConstant || !HasConstantValueInSignature) && (!defaultValueAssignmentAllowed || !IsOptional))
if (!IsDecimalConstant && HasConstantValueInSignature && !defaultValueAssignmentAllowed)
{
b.Add(KnownAttribute.DefaultParameterValue, KnownTypeCode.Object, GetConstantValue(throwOnInvalidMetadata: false));
}
Expand Down
39 changes: 39 additions & 0 deletions ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,45 @@ public static IAttribute GetAttribute(this IParameter parameter, KnownAttribute
}
#endregion

#region IParameter.IsDefaultValueAssignmentAllowed
/// <summary>
/// Checks if the parameter is allowed to be assigned a default value.
/// </summary>
/// <remarks>
/// This checks <see cref="IParameter.IsOptional"/>, <see cref="IParameter.HasConstantValueInSignature"/>, <see cref="IParameter.ReferenceKind"/>,
/// and <see cref="IParameter.IsParams"/> on this parameter and all subsequent parameters.
/// If the parameter has no <see cref="IParameter.Owner"/>, it does not check subsequent parameters.
/// </remarks>
/// <param name="parameter">The parameter</param>
/// <returns>True if the <paramref name="parameter"/> has a default value and is allowed to be assigned a default value.</returns>
public static bool IsDefaultValueAssignmentAllowed(this IParameter parameter)
{
if (!DefaultValueAssignmentAllowedIndividual(parameter))
return false;

if (parameter.Owner == null)
return true; // Shouldn't happen, but we need to check for it.

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;
}
}
#endregion

#region IAssembly.GetTypeDefinition(string,string,int)
/// <summary>
/// Gets the type definition for a top-level type.
Expand Down
Loading