-
Notifications
You must be signed in to change notification settings - Fork 762
/
Copy pathCategoryBucketGenerator.cs
87 lines (72 loc) · 2.53 KB
/
CategoryBucketGenerator.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.CodeAnalysis;
using Uno.Extensions;
namespace Uno.Samples.UITest.Generator
{
[Generator]
public class CategoryBucketGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
}
public void Execute(GeneratorExecutionContext context)
{
#if DEBUG
// Debugger.Launch();
#endif
GenerateTests(context);
}
private static void GenerateTests(GeneratorExecutionContext context)
{
if (context.Compilation.Assembly.Name == "SamplesApp.UITests")
{
var testAttribute = context.Compilation.GetTypeByMetadataName("NUnit.Framework.TestAttribute");
var query = from typeSymbol in context.Compilation.SourceModule.GlobalNamespace.GetNamespaceTypes()
where typeSymbol.DeclaredAccessibility == Accessibility.Public
where typeSymbol.GetMembers().OfType<IMethodSymbol>().Any(m => m.FindAttributeFlattened(testAttribute) != null)
select typeSymbol;
GenerateCategories(context, query);
}
}
private static void GenerateCategories(
GeneratorExecutionContext context,
IEnumerable<INamedTypeSymbol> symbols)
{
using var sha1 = SHA1.Create();
int.TryParse(Environment.GetEnvironmentVariable("UNO_UITEST_BUCKET_COUNT"), out var bucketCount);
foreach (var type in symbols)
{
var fullMetadataName = type.GetFullMetadataName();
var builder = new IndentedStringBuilder();
builder.AppendLineIndented("// <auto-generated />");
using (builder.BlockInvariant($"namespace {type.ContainingNamespace}"))
{
if (bucketCount != 0)
{
// Compute a stable hash of the full metadata name
var buffer = Encoding.UTF8.GetBytes(fullMetadataName);
var hash = sha1.ComputeHash(buffer);
var hashPart64 = BitConverter.ToUInt64(hash, 0);
var testCategoryBucket = (hashPart64 % (uint)bucketCount) + 1;
builder.AppendLineIndented($"[global::NUnit.Framework.Category(\"testBucket:{testCategoryBucket}\")]");
}
// Always generate the namespace property, so we can
builder.AppendLineIndented($"[global::NUnit.Framework.Property(\"Namespace\", \"{type.ContainingNamespace}\")]");
using (builder.BlockInvariant($"partial class {type.Name}"))
{
}
}
context.AddSource(Sanitize(fullMetadataName), builder.ToString());
}
}
private static string Sanitize(string category)
=> category
.Replace(' ', '_')
.Replace('-', '_')
.Replace('.', '_');
}
}