Browse Source

Merge pull request #3572 from ds5678/issue3571

Fix lower case type name conflicting with variable name
pull/3579/head
Siegfried Pammer 3 months ago committed by GitHub
parent
commit
4ed73717e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .github/workflows/build-ilspy.yml
  2. 4
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  3. 18
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  4. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs
  5. 33
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs
  6. 33
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs
  7. 37
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs
  8. 8
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs
  9. 10
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs
  10. 10
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  11. 2
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  12. 34
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

6
.github/workflows/build-ilspy.yml

@ -65,6 +65,9 @@ jobs: @@ -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 }}
@ -81,9 +84,6 @@ jobs: @@ -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'

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

@ -155,6 +155,10 @@ @@ -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" />

18
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -678,6 +678,24 @@ namespace ICSharpCode.Decompiler.Tests @@ -678,6 +678,24 @@ namespace ICSharpCode.Decompiler.Tests
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)
{

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Discards.cs

@ -43,12 +43,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -43,12 +43,6 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
GetOut(out var _);
}
public void DiscardedOutVsLambdaParameter()
{
GetOut(out var _);
MakeValue((@_ _) => 5);
}
public void ExplicitlyTypedDiscard()
{
GetOutOverloaded(out string _);

33
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs

@ -0,0 +1,33 @@ @@ -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
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs

@ -0,0 +1,33 @@ @@ -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
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs

@ -0,0 +1,37 @@ @@ -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);
}
}
}

8
ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs

@ -305,14 +305,6 @@ namespace ICSharpCode.Decompiler.Tests.Pretty @@ -305,14 +305,6 @@ namespace ICSharpCode.Decompiler.Tests.Pretty
{
System.Array.Sort(Array);
}
private void LocalConflictsWithTypeName()
{
for (int i = 0; i < 10; i++)
{
QualifierTests.i.Test();
}
}
#if CS70
private void LocalConflictsWithLocalFunction()
{

10
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoLocalFunctions.Expected.cs

@ -51,12 +51,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly @@ -51,12 +51,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly
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
}

10
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -551,7 +551,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -551,7 +551,7 @@ namespace ICSharpCode.Decompiler.CSharp
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)
@ -712,12 +712,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -712,12 +712,12 @@ namespace ICSharpCode.Decompiler.CSharp
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));
@ -725,11 +725,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -725,11 +725,11 @@ namespace ICSharpCode.Decompiler.CSharp
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)));

2
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -227,7 +227,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -227,7 +227,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
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)

34
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -28,6 +28,7 @@ using Humanizer.Inflections; @@ -28,6 +28,7 @@ using Humanizer.Inflections;
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;
@ -110,6 +111,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -110,6 +111,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
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
@ -618,6 +624,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -618,6 +624,21 @@ namespace ICSharpCode.Decompiler.IL.Transforms
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)
@ -870,7 +891,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -870,7 +891,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
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);
@ -889,14 +910,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -889,14 +910,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms
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)
@ -905,7 +927,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -905,7 +927,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
return existingVariable.Name;
}
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts);
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts, usingScope);
string baseName = GetNameFromInstruction(valueContext);
if (string.IsNullOrEmpty(baseName))
@ -955,13 +977,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -955,13 +977,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
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";

Loading…
Cancel
Save