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
6 changes: 3 additions & 3 deletions .github/workflows/build-ilspy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ jobs:
- name: Build
run: msbuild ILSpy.sln /p:Configuration=${{ matrix.configuration }} /p:Platform=$env:BuildPlatform /m

- name: Format check
run: dotnet-format whitespace --verify-no-changes --verbosity detailed ILSpy.sln

- name: Execute unit tests
run: dotnet test --solution ilspy.sln --configuration ${{ matrix.configuration }} --no-build --report-trx --results-directory test-results/${{ matrix.configuration }}

Expand All @@ -81,9 +84,6 @@ jobs:
with:
paths: "test-results/${{ matrix.configuration }}/*.trx"
folded: true

- name: Format check
run: dotnet-format whitespace --verify-no-changes --verbosity detailed ILSpy.sln

- name: Verify package contents
if: matrix.configuration == 'debug'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@
<Compile Include="TestCases\Pretty\ExpandParamsArgumentsDisabled.cs" />
<Compile Include="TestCases\Pretty\ExtensionProperties.cs" />
<Compile Include="TestCases\Pretty\Issue3541.cs" />
<Compile Include="TestCases\Pretty\Issue3571_C.cs" />
<Compile Include="TestCases\Pretty\Issue3571_B.cs" />
<Compile Include="TestCases\Pretty\Issue3571_A.cs" />
<None Include="TestCases\Ugly\NoLocalFunctions.Expected.cs" />
<None Include="TestCases\ILPretty\Issue3504.cs" />
<Compile Include="TestCases\ILPretty\MonoFixed.cs" />
<Compile Include="TestCases\Pretty\Comparisons.cs" />
Expand Down
18 changes: 18 additions & 0 deletions ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,24 @@ public async Task Issue3541([ValueSource(nameof(roslyn4OrNewerWithNet40Options))
await RunForLibrary(cscOptions: cscOptions);
}

[Test]
public async Task Issue3571_A([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}

[Test]
public async Task Issue3571_B([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}

[Test]
public async Task Issue3571_C([ValueSource(nameof(roslyn2OrNewerWithNet40Options))] CompilerOptions cscOptions)
{
await RunForLibrary(cscOptions: cscOptions);
}

[Test]
public async Task AssemblyCustomAttributes([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{
Expand Down
6 changes: 0 additions & 6 deletions ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ public void ParameterHiddenByLocal(@_ _)
GetOut(out var _);
}

public void DiscardedOutVsLambdaParameter()
{
GetOut(out var _);
MakeValue((@_ _) => 5);
}

public void ExplicitlyTypedDiscard()
{
GetOutOverloaded(out string _);
Expand Down
33 changes: 33 additions & 0 deletions ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Runtime.InteropServices;

namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal static class Issue3571_A
{
[StructLayout(LayoutKind.Sequential, Size = 1)]
public readonly struct fsResult
{
public static fsResult Success => default(fsResult);
public static fsResult Failure => default(fsResult);
public bool Succeeded => true;
public bool Failed => false;
public static fsResult operator +(fsResult a, fsResult b)
{
return default(fsResult);
}
}

public static fsResult M()
{
fsResult success = fsResult.Success;
fsResult fsResult2 = success + fsResult.Success;
if (fsResult2.Succeeded)
{
return success;
}
Console.WriteLine("Failed");
return fsResult2 + fsResult.Failure;
}
}
}
33 changes: 33 additions & 0 deletions ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Runtime.InteropServices;

namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3571_B
{
[StructLayout(LayoutKind.Sequential, Size = 1)]
public readonly struct fsResult
{
public static fsResult Success => default(fsResult);
public static fsResult Failure => default(fsResult);
public bool Succeeded => true;
public bool Failed => false;
public static fsResult operator +(fsResult a, fsResult b)
{
return default(fsResult);
}
}

internal static class Issue3571_B
{
public static fsResult M()
{
fsResult success = fsResult.Success;
fsResult fsResult2 = success + fsResult.Success;
if (fsResult2.Succeeded)
{
return success;
}
Console.WriteLine("Failed");
return fsResult2 + fsResult.Failure;
}
}
}
37 changes: 37 additions & 0 deletions ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Runtime.InteropServices;

using ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3571_Helper;

namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal static class Issue3571_C
{
public static fsResult M()
{
fsResult success = fsResult.Success;
fsResult fsResult2 = success + fsResult.Success;
if (fsResult2.Succeeded)
{
return success;
}
Console.WriteLine("Failed");
return fsResult2 + fsResult.Failure;
}
}
}
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.Issue3571_Helper
{
[StructLayout(LayoutKind.Sequential, Size = 1)]
public readonly struct fsResult
{
public static fsResult Success => default(fsResult);
public static fsResult Failure => default(fsResult);
public bool Succeeded => true;
public bool Failed => false;
public static fsResult operator +(fsResult a, fsResult b)
{
return default(fsResult);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,6 @@ private void ParameterConflictsWithTypeName(string[] Array)
{
System.Array.Sort(Array);
}

private void LocalConflictsWithTypeName()
{
for (int i = 0; i < 10; i++)
{
QualifierTests.i.Test();
}
}
#if CS70
private void LocalConflictsWithLocalFunction()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ private static void SimpleCapture()

private static void SimpleCaptureWithRef()
{
_003C_003Ec__DisplayClass2_0 _003C_003Ec__DisplayClass2_ = new _003C_003Ec__DisplayClass2_0();
_003C_003Ec__DisplayClass2_.x = 1;
#if OPT
new Handle(new Func<int>(_003C_003Ec__DisplayClass2_._003CSimpleCaptureWithRef_003Eg__F_007C0));
_003C_003Ec__DisplayClass2_0 obj = new _003C_003Ec__DisplayClass2_0();
obj.x = 1;
new Handle(new Func<int>(obj._003CSimpleCaptureWithRef_003Eg__F_007C0));
#else
Handle handle = new Handle(new Func<int>(_003C_003Ec__DisplayClass2_._003CSimpleCaptureWithRef_003Eg__F_007C0));
_003C_003Ec__DisplayClass2_0 _003C_003Ec__DisplayClass2_1 = new _003C_003Ec__DisplayClass2_0();
_003C_003Ec__DisplayClass2_1.x = 1;
Handle handle = new Handle(new Func<int>(_003C_003Ec__DisplayClass2_1._003CSimpleCaptureWithRef_003Eg__F_007C0));
#endif
}

Expand Down
10 changes: 5 additions & 5 deletions ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ protected internal override TranslatedStatement VisitUsingInstruction(UsingInstr
var.Kind = VariableKind.Local;
var disposeVariable = currentFunction.RegisterVariable(
VariableKind.Local, disposeType,
AssignVariableNames.GenerateVariableName(currentFunction, disposeType)
AssignVariableNames.GenerateVariableName(currentFunction, disposeType, decompileRun.UsingScope)
);
Expression disposeInvocation = new InvocationExpression(new MemberReferenceExpression(exprBuilder.ConvertVariable(disposeVariable).Expression, disposeTypeMethodName));
if (inst.IsAsync)
Expand Down Expand Up @@ -712,24 +712,24 @@ Statement TransformToForeach(UsingInstruction inst, Expression resource)
if (foreachVariable.Type.Kind != TypeKind.Dynamic)
foreachVariable.Type = type;
foreachVariable.Kind = VariableKind.ForeachLocal;
foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>(), foreachVariable);
foreachVariable.Name = AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>(), decompileRun.UsingScope, foreachVariable);
break;
case RequiredGetCurrentTransformation.IntroduceNewVariable:
foreachVariable = currentFunction.RegisterVariable(
VariableKind.ForeachLocal, type,
AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>())
AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>(), decompileRun.UsingScope)
);
instToReplace.ReplaceWith(new LdLoc(foreachVariable));
body.Instructions.Insert(0, new StLoc(foreachVariable, instToReplace));
break;
case RequiredGetCurrentTransformation.IntroduceNewVariableAndLocalCopy:
foreachVariable = currentFunction.RegisterVariable(
VariableKind.ForeachLocal, type,
AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>())
AssignVariableNames.GenerateForeachVariableName(currentFunction, collectionExpr.Annotation<ILInstruction>(), decompileRun.UsingScope)
);
var localCopyVariable = currentFunction.RegisterVariable(
VariableKind.Local, type,
AssignVariableNames.GenerateVariableName(currentFunction, type)
AssignVariableNames.GenerateVariableName(currentFunction, type, decompileRun.UsingScope)
);
instToReplace.Parent.ReplaceWith(new LdLoca(localCopyVariable));
body.Instructions.Insert(0, new StLoc(localCopyVariable, new LdLoc(foreachVariable)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ void EnsureExpressionStatementsAreValid(AstNode rootNode)
var v = function.RegisterVariable(
VariableKind.StackSlot,
type,
AssignVariableNames.GenerateVariableName(function, type,
AssignVariableNames.GenerateVariableName(function, type, context.DecompileRun.UsingScope,
stmt.Expression.Annotations.OfType<ILInstruction>()
.Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault(),
mustResolveConflicts: true)
Expand Down
34 changes: 28 additions & 6 deletions ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
Expand Down Expand Up @@ -110,6 +111,11 @@ public VariableScope(ILFunction function, ILTransformContext context, VariableSc
currentLowerCaseTypeOrMemberNames.Add(name);
AddExistingName(reservedVariableNames, name);
}
foreach (var name in CollectAllLowerCaseTypeNames(context.UsingScope))
{
currentLowerCaseTypeOrMemberNames.Add(name);
AddExistingName(reservedVariableNames, name);
}
this.currentLowerCaseTypeOrMemberNames = currentLowerCaseTypeOrMemberNames.ToImmutableHashSet();

// handle implicit parameters of set or event accessors
Expand Down Expand Up @@ -618,6 +624,21 @@ static IEnumerable<string> CollectAllLowerCaseTypeNames(ITypeDefinition type)
if (IsLowerCase(item.Name))
yield return item.Name;
}
var current = type;
while (current != null)
{
foreach (var nested in current.NestedTypes)
{
if (IsLowerCase(nested.Name))
yield return nested.Name;
}
current = current.DeclaringTypeDefinition;
}
}

static IEnumerable<string> CollectAllLowerCaseTypeNames(UsingScope usingScope)
{
return usingScope?.Usings.SelectMany(n => n.Types).Select(t => t.Name).Where(IsLowerCase) ?? [];
}

static bool IsLowerCase(string name)
Expand Down Expand Up @@ -870,7 +891,7 @@ static IType GuessType(IType variableType, ILInstruction inst, ILTransformContex
}

static Dictionary<string, int> CollectReservedVariableNames(ILFunction function,
ILVariable existingVariable, bool mustResolveConflicts)
ILVariable existingVariable, bool mustResolveConflicts, UsingScope usingScope)
{
var reservedVariableNames = new Dictionary<string, int>();
var rootFunction = function.Ancestors.OfType<ILFunction>().Single(f => f.Parent == null);
Expand All @@ -889,14 +910,15 @@ static Dictionary<string, int> CollectReservedVariableNames(ILFunction function,
if (mustResolveConflicts)
{
var memberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition)
.Concat(CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition));
.Concat(CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition))
.Concat(CollectAllLowerCaseTypeNames(usingScope));
foreach (var name in memberNames)
AddExistingName(reservedVariableNames, name);
}
return reservedVariableNames;
}

internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext,
internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, UsingScope usingScope,
ILVariable existingVariable = null, bool mustResolveConflicts = false)
{
if (function == null)
Expand All @@ -905,7 +927,7 @@ internal static string GenerateForeachVariableName(ILFunction function, ILInstru
{
return existingVariable.Name;
}
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts);
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts, usingScope);

string baseName = GetNameFromInstruction(valueContext);
if (string.IsNullOrEmpty(baseName))
Expand Down Expand Up @@ -955,13 +977,13 @@ internal static string GenerateForeachVariableName(ILFunction function, ILInstru
}
}

internal static string GenerateVariableName(ILFunction function, IType type,
internal static string GenerateVariableName(ILFunction function, IType type, UsingScope usingScope,
ILInstruction valueContext = null, ILVariable existingVariable = null,
bool mustResolveConflicts = false)
{
if (function == null)
throw new ArgumentNullException(nameof(function));
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts);
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts, usingScope);

string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type);
string proposedName = "obj";
Expand Down
Loading