Browse Source

Fix lower case type name conflicting with variable name

pull/3572/head
ds5678 3 months ago committed by Jeremy Pritts
parent
commit
c54318173b
  1. 3
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 18
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  3. 33
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_A.cs
  4. 33
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_B.cs
  5. 36
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs
  6. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/QualifierTests.cs
  7. 10
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  8. 2
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  9. 34
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

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

@ -155,6 +155,9 @@ @@ -155,6 +155,9 @@
<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\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)
{

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

36
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Issue3571_C.cs

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

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

@ -308,9 +308,9 @@ namespace ICSharpCode.Decompiler.Tests.Pretty @@ -308,9 +308,9 @@ namespace ICSharpCode.Decompiler.Tests.Pretty
private void LocalConflictsWithTypeName()
{
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
{
QualifierTests.i.Test();
i.Test();
}
}
#if CS70

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