-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#78 - переписал SG на полностью автоматическую генерацию паттерна рег…
…улярки (#115) * #78 - переписал SG на полностью автоматическую генерацию паттерна регулярки * #78 - убрал лишние отступы
- Loading branch information
Showing
8 changed files
with
72 additions
and
116 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
...ure/HydraScript.Infrastructure.LexerRegexGenerator/DefaultTokenTypesJsonStringProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using HydraScript.Domain.FrontEnd.Lexer; | ||
|
||
namespace HydraScript.Infrastructure.LexerRegexGenerator; | ||
|
||
internal class DefaultTokenTypesJsonStringProvider : | ||
ITokenTypesJsonStringProvider | ||
{ | ||
public string TokenTypesJsonString => TokenTypesJson.String; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
...structure/HydraScript.Infrastructure.LexerRegexGenerator/ITokenTypesJsonStringProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace HydraScript.Infrastructure.LexerRegexGenerator; | ||
|
||
public interface ITokenTypesJsonStringProvider | ||
{ | ||
public string TokenTypesJsonString { get; } | ||
} |
85 changes: 14 additions & 71 deletions
85
src/Infrastructure/HydraScript.Infrastructure.LexerRegexGenerator/PatternGenerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,96 +1,39 @@ | ||
using System.Collections.Immutable; | ||
using System.Text; | ||
using System.Text.Json; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace HydraScript.Infrastructure.LexerRegexGenerator; | ||
|
||
[Generator] | ||
public partial class PatternGenerator : IIncrementalGenerator | ||
{ | ||
private const string AttributeSourceCode = @"// <auto-generated/> | ||
namespace HydraScript.Infrastructure; | ||
[System.AttributeUsage(System.AttributeTargets.Class)] | ||
public class PatternContainerAttribute<T>(string json) : System.Attribute | ||
where T : HydraScript.Domain.FrontEnd.Lexer.IGeneratedRegexContainer | ||
{ | ||
public string Json { get; } = json; | ||
} | ||
"; | ||
public ITokenTypesJsonStringProvider Provider { get; init; } = new DefaultTokenTypesJsonStringProvider(); | ||
|
||
public void Initialize(IncrementalGeneratorInitializationContext context) | ||
{ | ||
context.RegisterPostInitializationOutput(ctx => ctx.AddSource( | ||
"PatternContainerAttribute.g.cs", | ||
SourceText.From(AttributeSourceCode, Encoding.UTF8))); | ||
|
||
var provider = context.SyntaxProvider | ||
.ForAttributeWithMetadataName( | ||
"HydraScript.Infrastructure.PatternContainerAttribute`1", | ||
static (s, _) => IsSyntaxTargetForGeneration(s), | ||
static (ctx, _) => GetTypeDeclarationForSourceGen(ctx)) | ||
.Where(static x => x is not null) | ||
.Select(static (x, _) => x!); | ||
|
||
context.RegisterImplementationSourceOutput(provider.Collect(), GenerateCode); | ||
} | ||
|
||
private static bool IsSyntaxTargetForGeneration(SyntaxNode node) => | ||
node is ClassDeclarationSyntax candidate && | ||
candidate.Modifiers.Any(SyntaxKind.PartialKeyword) && | ||
candidate.Modifiers.Any(SyntaxKind.InternalKeyword); | ||
|
||
private static RegexContainerInfo? GetTypeDeclarationForSourceGen( | ||
GeneratorAttributeSyntaxContext context) | ||
{ | ||
var attribute = context.Attributes.FirstOrDefault(); | ||
if (attribute is null) | ||
return null; | ||
var visitable = (ClassDeclarationSyntax)context.TargetNode; | ||
var json = attribute.ConstructorArguments.First().Value!.ToString()!; | ||
return new RegexContainerInfo( | ||
ClassName: visitable.Identifier.Text, | ||
json); | ||
} | ||
var tokenTypes = JsonSerializer.Deserialize( | ||
Provider.TokenTypesJsonString, | ||
PatternGeneratorContext.Default.IEnumerableTokenType)! | ||
.OrderBy(x => x.Priority) | ||
.Concat([new TokenType("ERROR", @"\S+", int.MaxValue)]); | ||
var pattern = string.Join('|', tokenTypes.Select(t => t.GetNamedRegex())); | ||
|
||
private static void GenerateCode( | ||
SourceProductionContext context, | ||
ImmutableArray<RegexContainerInfo> containerInfos) | ||
{ | ||
foreach (var info in containerInfos) | ||
{ | ||
var tokenTypes = JsonSerializer.Deserialize( | ||
info.Json, | ||
PatternGeneratorContext.Default.IEnumerableTokenType)! | ||
.OrderBy(x => x.Priority) | ||
.Concat([new TokenType("ERROR", @"\S+", int.MaxValue)]); | ||
var pattern = string.Join('|', tokenTypes.Select(t => t.GetNamedRegex())); | ||
|
||
var code = $@"// <auto-generated/> | ||
var code = $@"// <auto-generated/> | ||
using System.Diagnostics.CodeAnalysis; | ||
namespace HydraScript.Infrastructure; | ||
internal partial class {info.ClassName} | ||
internal partial class PatternContainer | ||
{{ | ||
[StringSyntax(StringSyntaxAttribute.Regex)] | ||
public const string Pattern = | ||
"""""" | ||
{pattern} | ||
""""""; | ||
public const string Value = """"""{pattern}""""""; | ||
}} | ||
"; | ||
context.AddSource($"{info.ClassName}.g.cs", SourceText.From(code, Encoding.UTF8)); | ||
} | ||
} | ||
|
||
private record RegexContainerInfo( | ||
string ClassName, | ||
string Json); | ||
context.RegisterPostInitializationOutput(ctx => ctx.AddSource( | ||
"PatternContainer.g.cs", | ||
SourceText.From(code, Encoding.UTF8))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 37 additions & 30 deletions
67
tests/HydraScript.Infrastructure.LexerRegexGenerator.Tests/PatternGeneratorTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 0 additions & 13 deletions
13
tests/HydraScript.Tests/Unit/Infrastructure/GeneratedRegexContainerTests.cs
This file was deleted.
Oops, something went wrong.