Skip to content

Commit 28f4a00

Browse files
authored
Merge pull request #13 from ufcpp/roslyn_3_9_0
Roslyn 3 9 0
2 parents 9bcfc86 + 0314645 commit 28f4a00

File tree

8 files changed

+230
-174
lines changed

8 files changed

+230
-174
lines changed

samples/StringLiteralCodeAnalysisSample/StringLiteralCodeAnalysisSample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
9+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
1010
</ItemGroup>
1111

1212
<ItemGroup>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"profiles": {
3+
"StringLiteralGenerator": {
4+
"commandName": "DebugRoslynComponent",
5+
"targetProject": "..\\..\\samples\\StringLiteralSample\\StringLiteralSample.csproj"
6+
}
7+
}
8+
}

src/StringLiteralGenerator/StringLiteralGenerator.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<LangVersion>preview</LangVersion>
66
<Nullable>enable</Nullable>
7+
<IsRoslynComponent>true</IsRoslynComponent>
78
<IncludeBuildOutput>false</IncludeBuildOutput>
89

910
<PackageId>StringLiteralGenerator</PackageId>
@@ -18,7 +19,7 @@
1819
</PropertyGroup>
1920

2021
<ItemGroup>
21-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.8.0" PrivateAssets="all" />
22+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.9.0" PrivateAssets="all" />
2223
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
2324
</ItemGroup>
2425

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.CodeAnalysis;
2+
3+
namespace StringLiteralGenerator;
4+
5+
public partial class Utf8StringLiteralGenerator
6+
{
7+
private record struct TypeInfo(string? Namespace, string Name)
8+
{
9+
public TypeInfo(INamedTypeSymbol t)
10+
: this(GetNamespace(t), t.Name)
11+
{ }
12+
13+
private static string? GetNamespace(INamedTypeSymbol t)
14+
{
15+
var x = t.ContainingNamespace;
16+
return string.IsNullOrEmpty(x.Name) ? null : x.ToDisplayString();
17+
}
18+
}
19+
20+
private record struct MethodInfo(string Name, Accessibility Accessibility, string Text)
21+
{
22+
public MethodInfo(IMethodSymbol m, string text)
23+
: this(m.Name, m.DeclaredAccessibility, text)
24+
{ }
25+
}
26+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using Microsoft.CodeAnalysis;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace StringLiteralGenerator;
7+
8+
public partial class Utf8StringLiteralGenerator : ISourceGenerator
9+
{
10+
private static string GetFilename(TypeInfo type, StringBuilder buffer)
11+
{
12+
buffer.Clear();
13+
14+
if (type.Namespace is { } ns)
15+
{
16+
buffer.Append(ns.Replace('.', '_'));
17+
buffer.Append('_');
18+
}
19+
buffer.Append(type.Name);
20+
buffer.Append("_utf8literal.cs");
21+
22+
return buffer.ToString();
23+
}
24+
25+
private static string Generate(TypeInfo type, IEnumerable<MethodInfo> methods, StringBuilder buffer)
26+
{
27+
var (ns, name) = type;
28+
29+
buffer.Clear();
30+
buffer.AppendLine("// <auto-generated />");
31+
32+
if (ns is not null)
33+
{
34+
buffer.Append(@"namespace ");
35+
buffer.Append(ns);
36+
buffer.Append(@"
37+
{
38+
");
39+
}
40+
buffer.Append(@"partial class ");
41+
buffer.Append(name);
42+
buffer.Append(@"
43+
{
44+
");
45+
foreach (var (methodName, accessibility, value) in methods)
46+
{
47+
buffer.Append(" ");
48+
buffer.Append(AccessibilityText(accessibility));
49+
buffer.Append(" static partial System.ReadOnlySpan<byte> ");
50+
buffer.Append(methodName);
51+
buffer.Append("() => new byte[] {");
52+
53+
foreach (var b in Encoding.UTF8.GetBytes(value))
54+
{
55+
buffer.Append(b);
56+
buffer.Append(", ");
57+
}
58+
59+
buffer.Append(@"};
60+
");
61+
}
62+
63+
buffer.Append(@"}
64+
");
65+
if (ns is not null)
66+
{
67+
buffer.Append(@"}
68+
");
69+
}
70+
71+
return buffer.ToString();
72+
}
73+
74+
private static string AccessibilityText(Accessibility accessibility) => accessibility switch
75+
{
76+
Accessibility.Public => "public",
77+
Accessibility.Protected => "protected",
78+
Accessibility.Private => "private",
79+
Accessibility.Internal => "internal",
80+
Accessibility.ProtectedOrInternal => "protected internal",
81+
Accessibility.ProtectedAndInternal => "private protected",
82+
_ => throw new InvalidOperationException(),
83+
};
84+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.Text;
3+
using System.Text;
4+
5+
namespace StringLiteralGenerator;
6+
7+
public partial class Utf8StringLiteralGenerator : ISourceGenerator
8+
{
9+
private const string attributeText = @"// <auto-generated />
10+
using System;
11+
namespace StringLiteral
12+
{
13+
[System.Diagnostics.Conditional(""COMPILE_TIME_ONLY"")]
14+
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
15+
sealed class Utf8Attribute : Attribute
16+
{
17+
public Utf8Attribute(string s) { }
18+
}
19+
}
20+
";
21+
22+
private static void AddAttribute(GeneratorPostInitializationContext context)
23+
{
24+
context.AddSource("Utf8Attribute", SourceText.From(attributeText, Encoding.UTF8));
25+
}
26+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp.Syntax;
3+
4+
namespace StringLiteralGenerator;
5+
6+
public partial class Utf8StringLiteralGenerator : ISourceGenerator
7+
{
8+
private const string attributeName = "StringLiteral.Utf8Attribute";
9+
10+
private static bool IsStaticPartial(MemberDeclarationSyntax m)
11+
{
12+
bool isStatic = false;
13+
bool isPartial = false;
14+
foreach (var mod in m.Modifiers)
15+
{
16+
isStatic |= mod.Text == "static";
17+
isPartial |= mod.Text == "partial";
18+
}
19+
return isStatic && isPartial;
20+
}
21+
22+
static bool ReturnsString(IMethodSymbol methodSymbol)
23+
{
24+
return methodSymbol.ReturnType is INamedTypeSymbol s
25+
&& s.ToDisplayString() == "System.ReadOnlySpan<byte>";
26+
}
27+
28+
static string? GetUtf8Attribute(IMethodSymbol methodSymbol)
29+
{
30+
foreach (var a in methodSymbol.GetAttributes())
31+
{
32+
if (a.AttributeClass?.ToDisplayString() == attributeName)
33+
{
34+
var args = a.ConstructorArguments;
35+
if (args.Length != 1) continue;
36+
37+
if (args[0].Value is string value) return value;
38+
}
39+
}
40+
41+
return null;
42+
}
43+
}

0 commit comments

Comments
 (0)