Browse Source

Fix #1698: Readonly auto properties from VB.NET are not properly decompiled

issue1638
Siegfried Pammer 4 years ago
parent
commit
bc5d078feb
  1. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1325.cs
  3. 39
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBPropertiesTest.cs
  4. 37
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBPropertiesTest.vb
  5. 8
      ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
  6. 7
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  7. 11
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -107,6 +107,7 @@ @@ -107,6 +107,7 @@
<Compile Include="TestCases\Correctness\DeconstructionTests.cs" />
<Compile Include="TestCases\Correctness\DynamicTests.cs" />
<Compile Include="TestCases\Correctness\StringConcat.cs" />
<Compile Include="TestCases\VBPretty\VBPropertiesTest.cs" />
<None Include="TestCases\ILPretty\Issue2260SwitchString.cs" />
<None Include="TestCases\Pretty\Records.cs" />
<Compile Include="TestCases\VBPretty\Issue2192.cs" />
@ -308,6 +309,7 @@ @@ -308,6 +309,7 @@
<None Include="TestCases\Pretty\Readme.txt" />
<None Include="TestCases\VBPretty\VBCompoundAssign.vb" />
<None Include="TestCases\VBPretty\Async.vb" />
<None Include="TestCases\VBPretty\VBPropertiesTest.vb" />
</ItemGroup>
<ItemGroup>

6
ICSharpCode.Decompiler.Tests/TestCases/ILPretty/Issue1325.cs

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
@ -13,6 +12,8 @@ using Microsoft.VisualBasic.CompilerServices; @@ -13,6 +12,8 @@ using Microsoft.VisualBasic.CompilerServices;
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
#pragma warning disable format
namespace Issue1325
{
[StandardModule]
@ -34,9 +35,6 @@ namespace Issue1325 @@ -34,9 +35,6 @@ namespace Issue1325
internal class Test
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[CompilerGenerated]
private string _Unparameterized;
public string Parameterized {
get {
throw new NotImplementedException();

39
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBPropertiesTest.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
using System;
public class VBPropertiesTest
{
private int _fullProperty;
public int FullProperty {
get {
return _fullProperty;
}
set {
_fullProperty = value;
}
}
public int AutoProperty { get; set; }
#if ROSLYN
public int ReadOnlyAutoProperty { get; }
public VBPropertiesTest()
{
ReadOnlyAutoProperty = 32;
}
#endif
public void TestMethod()
{
FullProperty = 42;
_fullProperty = 24;
AutoProperty = 4711;
Console.WriteLine(AutoProperty);
Console.WriteLine(_fullProperty);
Console.WriteLine(FullProperty);
#if ROSLYN
Console.WriteLine(ReadOnlyAutoProperty);
#endif
}
}

37
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBPropertiesTest.vb

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
Imports System
Public Class VBPropertiesTest
Private _fullProperty As Integer
Property FullProperty As Integer
Get
Return _fullProperty
End Get
Set(value As Integer)
_fullProperty = value
End Set
End Property
Property AutoProperty As Integer
#If ROSLYN Then
ReadOnly Property ReadOnlyAutoProperty As Integer
Sub New()
Me.ReadOnlyAutoProperty = 32
End Sub
#End If
Sub TestMethod()
Me.FullProperty = 42
Me._fullProperty = 24
Me.AutoProperty = 4711
Console.WriteLine(Me.AutoProperty)
Console.WriteLine(Me._fullProperty)
Console.WriteLine(Me.FullProperty)
#If ROSLYN Then
Console.WriteLine(Me.ReadOnlyAutoProperty)
#End If
End Sub
End Class

8
ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs

@ -102,6 +102,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -102,6 +102,12 @@ namespace ICSharpCode.Decompiler.Tests
Run(options: options | CompilerOptions.Library);
}
[Test]
public void VBPropertiesTest([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
Run(options: options | CompilerOptions.Library);
}
void Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
{
var vbFile = Path.Combine(TestCasePath, testName + ".vb");
@ -115,7 +121,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -115,7 +121,7 @@ namespace ICSharpCode.Decompiler.Tests
var executable = Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile);
var decompiled = Tester.DecompileCSharp(executable.PathToAssembly, settings);
CodeAssert.FilesAreEqual(csFile, decompiled);
CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(options).ToArray());
}
}
}

7
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -386,7 +386,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -386,7 +386,7 @@ namespace ICSharpCode.Decompiler.CSharp
static readonly Regex automaticPropertyBackingFieldRegex = new Regex(@"^<(.*)>k__BackingField$",
RegexOptions.Compiled | RegexOptions.CultureInvariant);
static bool IsAutomaticPropertyBackingField(SRM.FieldDefinition field, MetadataReader metadata, out string propertyName)
static bool IsAutomaticPropertyBackingField(FieldDefinition field, MetadataReader metadata, out string propertyName)
{
propertyName = null;
var name = metadata.GetString(field.Name);
@ -396,6 +396,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -396,6 +396,11 @@ namespace ICSharpCode.Decompiler.CSharp
propertyName = m.Groups[1].Value;
return true;
}
if (name.StartsWith("_", StringComparison.Ordinal))
{
propertyName = name.Substring(1);
return field.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
}
return false;
}

11
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -592,15 +592,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -592,15 +592,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
};
bool CanTransformToAutomaticProperty(IProperty property)
bool CanTransformToAutomaticProperty(IProperty property, bool accessorsMustBeCompilerGenerated)
{
if (!property.CanGet)
return false;
if (!property.Getter.IsCompilerGenerated())
if (accessorsMustBeCompilerGenerated && !property.Getter.IsCompilerGenerated())
return false;
if (property.Setter is IMethod setter)
{
if (!setter.IsCompilerGenerated())
if (accessorsMustBeCompilerGenerated && !setter.IsCompilerGenerated())
return false;
if (setter.HasReadonlyModifier())
return false;
@ -611,7 +611,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -611,7 +611,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
PropertyDeclaration TransformAutomaticProperty(PropertyDeclaration propertyDeclaration)
{
IProperty property = propertyDeclaration.GetSymbol() as IProperty;
if (!CanTransformToAutomaticProperty(property))
if (!CanTransformToAutomaticProperty(property, !property.DeclaringTypeDefinition.Fields.Any(f => f.Name == "_" + property.Name && f.IsCompilerGenerated())))
return null;
IField field = null;
Match m = automaticPropertyPattern.Match(propertyDeclaration);
@ -741,7 +741,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -741,7 +741,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var mrr = parent.Annotation<MemberResolveResult>();
var field = mrr?.Member as IField;
if (field != null && IsBackingFieldOfAutomaticProperty(field, out var property)
&& CanTransformToAutomaticProperty(property) && currentMethod.AccessorOwner != property)
&& CanTransformToAutomaticProperty(property, !(field.IsCompilerGenerated() && field.Name == "_" + property.Name))
&& currentMethod.AccessorOwner != property)
{
if (!property.CanSet && !context.Settings.GetterOnlyAutomaticProperties)
return null;

Loading…
Cancel
Save