forked from dotnet/SqlClient
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRefToNotSupportedGenerator.cs
More file actions
105 lines (93 loc) · 4.37 KB
/
Copy pathRefToNotSupportedGenerator.cs
File metadata and controls
105 lines (93 loc) · 4.37 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.Data.SqlClient.SourceGenerator
{
[Generator]
public class RefToNotSupportedGenerator : IIncrementalGenerator
{
private const string DefaultFileHeader =
"//------------------------------------------------------------------------------\r\n" +
"// <auto-generated>\r\n" +
"// This code was generated by a tool.\r\n" +
"// {0}\r\n" +
"//\r\n" +
"// Changes to this file may cause incorrect behavior and will be lost if\r\n" +
"// the code is regenerated.\r\n" +
"// </auto-generated>\r\n" +
"//------------------------------------------------------------------------------\r\n";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
IncrementalValuesProvider<SyntaxNode> modelsProvider = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: (s, _) => IsSyntaxTargetForGeneration(s),
transform: (ctx, _) => ctx.Node)
.Where(m => m != null); // Filter out errors that we don't care about
var modelProvider = modelsProvider
.Collect()
.Combine(context.AnalyzerConfigOptionsProvider);
context.RegisterSourceOutput(
modelProvider,
(ctx, compilation) =>
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat(DefaultFileHeader, nameof(RefToNotSupportedGenerator));
using (StringWriter writer = new StringWriter(sb))
{
if (!compilation.Right.GlobalOptions.TryGetValue("build_property.targetframework", out string framework))
{
throw new KeyNotFoundException("build_property.targetframework");
}
try
{
sb.AppendLine("using System;");
sb.AppendLine("#if NOTSUPPORTED");
RefToNotsupportedTypeRewriter visitor = new RefToNotsupportedTypeRewriter();
// Group all collected types by namespace. Expects source file name from ref library to match namespace of all incuded types
foreach (var group in compilation.Left
.GroupBy(c => c.GetLocation().SourceTree.FilePath)
.OrderBy(cg => cg.Key)
)
{
sb.Append("namespace ");
sb.AppendLine(Path.GetFileNameWithoutExtension(group.Key));
sb.AppendLine("{");
foreach (SyntaxNode model in group)
{
SyntaxNode result = visitor.Visit(model);
result.WriteTo(writer);
}
sb.AppendLine("}");
}
sb.AppendLine("#endif");
}
catch (Exception ex)
{
sb.AppendLine($"// Exception: {ex.Message}\r\n// StackTrace: {ex.StackTrace}");
}
ctx.AddSource($"Microsoft.Data.SqlClient.{framework}.notsupported.g.cs", sb.ToString());
}
});
}
private static bool IsSyntaxTargetForGeneration(SyntaxNode node)
{
// Public delegates
if (node is DelegateDeclarationSyntax membDecl && membDecl.Modifiers.Any(SyntaxKind.PublicKeyword))
{
return true;
}
// Public, or internal types
if (node is BaseTypeDeclarationSyntax typeDecl &&
(typeDecl.Modifiers.Any(SyntaxKind.PublicKeyword) || typeDecl.Modifiers.Any(SyntaxKind.InternalKeyword)))
{
return true;
}
return false;
}
}
}