Skip to content

Commit fa50e8d

Browse files
Add non-embedded attributes to all tests that use older framework versions.
1 parent 7d715a4 commit fa50e8d

File tree

6 files changed

+66
-49
lines changed

6 files changed

+66
-49
lines changed

ICSharpCode.Decompiler.Tests/Helpers/Tester.cs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
using System;
2020
using System.Collections.Generic;
21-
using System.Diagnostics;
2221
using System.IO;
2322
using System.Linq;
2423
using System.Reflection.PortableExecutable;
@@ -330,6 +329,45 @@ static string GetTargetFrameworkAttributeSnippetFile()
330329
return tempFile;
331330
}
332331

332+
const string nonEmbeddedAttributesSnippet = @"
333+
using System;
334+
335+
#if !NET60
336+
namespace System.Runtime.CompilerServices
337+
{
338+
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
339+
internal sealed class CompilerFeatureRequiredAttribute : Attribute
340+
{
341+
public CompilerFeatureRequiredAttribute(string featureName)
342+
{
343+
}
344+
}
345+
346+
internal class IsExternalInit
347+
{
348+
}
349+
#endif
350+
#if !NET70
351+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
352+
internal sealed class RequiredMemberAttribute : Attribute
353+
{
354+
}
355+
#endif
356+
#if !NET60
357+
}
358+
#endif
359+
";
360+
361+
static readonly Lazy<string> nonEmbeddedAttributesSnippetFile = new Lazy<string>(GetNonEmbeddedAttributesSnippetFile);
362+
363+
static string GetNonEmbeddedAttributesSnippetFile()
364+
{
365+
// Note: this leaks a temporary file, we're not attempting to delete it, because it is only one.
366+
var tempFile = Path.GetTempFileName();
367+
File.WriteAllText(tempFile, nonEmbeddedAttributesSnippet);
368+
return tempFile;
369+
}
370+
333371
public static List<string> GetPreprocessorSymbols(CompilerOptions flags)
334372
{
335373
var preprocessorSymbols = new List<string>();
@@ -419,6 +457,11 @@ public static async Task<CompilerResults> CompileCSharp(string sourceFileName, C
419457
sourceFileNames.Add(targetFrameworkAttributeSnippetFile.Value);
420458
}
421459

460+
if (targetNet40)
461+
{
462+
sourceFileNames.Add(nonEmbeddedAttributesSnippetFile.Value);
463+
}
464+
422465
var preprocessorSymbols = GetPreprocessorSymbols(flags);
423466

424467
if ((flags & CompilerOptions.UseMcsMask) == 0)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
<None Include="TestCases\Pretty\CovariantReturns.cs" />
152152
<Compile Include="TestCases\VBPretty\VBPropertiesTest.cs" />
153153
<None Include="TestCases\ILPretty\Issue2260SwitchString.cs" />
154-
<None Include="TestCases\Pretty\Records.cs" />
154+
<Compile Include="TestCases\Pretty\Records.cs" />
155155
<Compile Include="TestCases\VBPretty\Issue2192.cs" />
156156
<Compile Include="Util\FileUtilityTests.cs" />
157157
<Compile Include="TestCases\Pretty\FunctionPointers.cs" />

ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public record Pair<A, B>
4444
public record PairWithPrimaryCtor<A, B>(A First, B Second);
4545

4646
public record PrimaryCtor(int A, string B);
47-
public record PrimaryCtorWithAttribute([RecordTest("param")] [property: RecordTest("property")][field: RecordTest("field")] int a);
47+
public record PrimaryCtorWithAttribute([RecordTest("param")][property: RecordTest("property")][field: RecordTest("field")] int a);
4848
public record PrimaryCtorWithField(int A, string B)
4949
{
5050
public double C = 1.0;
@@ -169,7 +169,7 @@ public record struct Pair<A, B>
169169
public record struct PairWithPrimaryCtor<A, B>(A First, B Second);
170170

171171
public record struct PrimaryCtor(int A, string B);
172-
public record struct PrimaryCtorWithAttribute([RecordTest("param")] [property: RecordTest("property")][field: RecordTest("field")] int a);
172+
public record struct PrimaryCtorWithAttribute([RecordTest("param")][property: RecordTest("property")][field: RecordTest("field")] int a);
173173
public record struct PrimaryCtorWithField(int A, string B)
174174
{
175175
public double C = 1.0;
@@ -242,27 +242,3 @@ public record struct WithRequiredMembers
242242
}
243243
#endif
244244
}
245-
#if !NET60
246-
namespace System.Runtime.CompilerServices
247-
{
248-
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
249-
internal sealed class CompilerFeatureRequiredAttribute : Attribute
250-
{
251-
public CompilerFeatureRequiredAttribute(string featureName)
252-
{
253-
}
254-
}
255-
256-
internal class IsExternalInit
257-
{
258-
}
259-
#endif
260-
#if !NET70
261-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
262-
internal sealed class RequiredMemberAttribute : Attribute
263-
{
264-
}
265-
#endif
266-
#if !NET60
267-
}
268-
#endif

ICSharpCode.Decompiler.Tests/TestCases/Pretty/Structs.cs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,4 @@ public struct StructWithRequiredMembers
5959
public required string LastName { get; set; }
6060
}
6161
#endif
62-
}
63-
64-
namespace System.Runtime.CompilerServices
65-
{
66-
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
67-
internal sealed class CompilerFeatureRequiredAttribute : Attribute
68-
{
69-
public CompilerFeatureRequiredAttribute(string featureName)
70-
{
71-
}
72-
}
73-
74-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
75-
internal sealed class RequiredMemberAttribute : Attribute
76-
{
77-
}
78-
}
62+
}

ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,8 +1530,8 @@ public virtual void VisitAttributeSection(AttributeSection attributeSection)
15301530
WriteToken(Roles.RBracket);
15311531
switch (attributeSection.Parent)
15321532
{
1533-
case ParameterDeclaration _:
1534-
if (attributeSection.NextSibling is AttributeSection)
1533+
case ParameterDeclaration pd:
1534+
if (pd.Attributes.Last() != attributeSection)
15351535
Space(policy.SpaceBetweenParameterAttributeSections);
15361536
else
15371537
Space();

ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,27 @@ public class RemoveEmbeddedAttributes : DepthFirstAstVisitor, IAstTransform
172172
"Microsoft.CodeAnalysis.EmbeddedAttribute",
173173
};
174174

175+
internal static readonly HashSet<string> nonEmbeddedAttributeNames = new HashSet<string>() {
176+
// non-embedded attributes, but we still want to remove them
177+
"System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute",
178+
"System.Runtime.CompilerServices.RequiredMemberAttribute",
179+
"System.Runtime.CompilerServices.IsExternalInit",
180+
};
181+
175182
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
176183
{
177184
var typeDefinition = typeDeclaration.GetSymbol() as ITypeDefinition;
178-
if (typeDefinition == null || !attributeNames.Contains(typeDefinition.FullName))
185+
if (typeDefinition == null)
179186
return;
180-
if (!typeDefinition.HasAttribute(KnownAttribute.Embedded))
187+
188+
if (attributeNames.Contains(typeDefinition.FullName))
189+
{
190+
if (!typeDefinition.HasAttribute(KnownAttribute.Embedded))
191+
return;
192+
}
193+
else if (!nonEmbeddedAttributeNames.Contains(typeDefinition.FullName))
181194
return;
195+
182196
if (typeDeclaration.Parent is NamespaceDeclaration ns && ns.Members.Count == 1)
183197
ns.Remove();
184198
else

0 commit comments

Comments
 (0)