From 4d2a4eeb1819b865d60dd330a2950e609dd7afb2 Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:44:29 +0800 Subject: [PATCH] text regex source gen framework is briefly done. Going on ir2code --- GenerateGL.sln | 4 +- .../Abstraction/SequenceEmitter.cs | 42 +++++- .../RegexAnalyzer.SourceGen.CharSetEmitter.cs | 105 -------------- .../Text/TextRegexSourceGen.Diagnostic.cs | 7 + ...eGen.cs => TextRegexSourceGen.GenClass.cs} | 21 +-- .../Text/TextRegexSourceGen.GenFile.cs | 133 ++++++++++++++++++ .../Text/TextRegexSourceGen.Source.cs | 53 +++++-- .../Text/TextRegexSourceGen.cs | 51 ++++++- .../CodeGen/CsTypeMapper.cs | 0 .../StgSharp.GenerateGL/CodeGen/Generator.cs | 0 .../CodeGen/GlXmlParser.cs | 0 .../StgSharp.GenerateGL/CodeGen/Models.cs | 0 .../Docs/SourceGenerator.md | 0 .../StgSharp.GenerateGL/GenerateGL.csproj | 0 {src => test}/StgSharp.GenerateGL/Program.cs | 0 {src => test}/StgSharp.GenerateGL/gl.h | 0 .../StgSharp.GenerateGL/xml/Genglvnd | 0 .../StgSharp.GenerateGL/xml/README.adoc | 0 .../StgSharp.GenerateGL/xml/genglvnd.py | 0 .../StgSharp.GenerateGL/xml/genheaders.py | 0 {src => test}/StgSharp.GenerateGL/xml/gl.xml | 0 {src => test}/StgSharp.GenerateGL/xml/glx.xml | 0 .../xml/glxproto.reserved.txt | 0 .../StgSharp.GenerateGL/xml/readme.pdf | Bin .../StgSharp.GenerateGL/xml/readme.tex | 0 {src => test}/StgSharp.GenerateGL/xml/reg.py | 0 .../StgSharp.GenerateGL/xml/registry.rnc | 0 .../StgSharp.GenerateGL/xml/testesext.c | 0 .../StgSharp.GenerateGL/xml/testglext.c | 0 .../StgSharp.GenerateGL/xml/vendors.txt | 0 {src => test}/StgSharp.GenerateGL/xml/wgl.xml | 0 .../StgSharp.GenerateGL/xml/wgltypes.txt | 0 32 files changed, 276 insertions(+), 140 deletions(-) delete mode 100644 src/StgSharp.RegularAnalysis/Text/RegexAnalyzer.SourceGen.CharSetEmitter.cs rename src/StgSharp.RegularAnalysis/Text/{RegexAnalyzer.SourceGen.cs => TextRegexSourceGen.GenClass.cs} (81%) create mode 100644 src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs rename {src => test}/StgSharp.GenerateGL/CodeGen/CsTypeMapper.cs (100%) rename {src => test}/StgSharp.GenerateGL/CodeGen/Generator.cs (100%) rename {src => test}/StgSharp.GenerateGL/CodeGen/GlXmlParser.cs (100%) rename {src => test}/StgSharp.GenerateGL/CodeGen/Models.cs (100%) rename {src => test}/StgSharp.GenerateGL/Docs/SourceGenerator.md (100%) rename {src => test}/StgSharp.GenerateGL/GenerateGL.csproj (100%) rename {src => test}/StgSharp.GenerateGL/Program.cs (100%) rename {src => test}/StgSharp.GenerateGL/gl.h (100%) rename {src => test}/StgSharp.GenerateGL/xml/Genglvnd (100%) rename {src => test}/StgSharp.GenerateGL/xml/README.adoc (100%) rename {src => test}/StgSharp.GenerateGL/xml/genglvnd.py (100%) rename {src => test}/StgSharp.GenerateGL/xml/genheaders.py (100%) rename {src => test}/StgSharp.GenerateGL/xml/gl.xml (100%) rename {src => test}/StgSharp.GenerateGL/xml/glx.xml (100%) rename {src => test}/StgSharp.GenerateGL/xml/glxproto.reserved.txt (100%) rename {src => test}/StgSharp.GenerateGL/xml/readme.pdf (100%) rename {src => test}/StgSharp.GenerateGL/xml/readme.tex (100%) rename {src => test}/StgSharp.GenerateGL/xml/reg.py (100%) rename {src => test}/StgSharp.GenerateGL/xml/registry.rnc (100%) rename {src => test}/StgSharp.GenerateGL/xml/testesext.c (100%) rename {src => test}/StgSharp.GenerateGL/xml/testglext.c (100%) rename {src => test}/StgSharp.GenerateGL/xml/vendors.txt (100%) rename {src => test}/StgSharp.GenerateGL/xml/wgl.xml (100%) rename {src => test}/StgSharp.GenerateGL/xml/wgltypes.txt (100%) diff --git a/GenerateGL.sln b/GenerateGL.sln index dc07a6b6..14e45def 100644 --- a/GenerateGL.sln +++ b/GenerateGL.sln @@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.14.36705.20 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenerateGL", "StgSharp.GenerateGL\GenerateGL.csproj", "{9FD27EE6-E94D-4E64-A13B-5A349DEA215A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenerateGL", "test\StgSharp.GenerateGL\GenerateGL.csproj", "{9FD27EE6-E94D-4E64-A13B-5A349DEA215A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StgSharp.Common", "StgSharp.Common\StgSharp.Common.csproj", "{5D646C0E-CCF8-B5B4-7DE8-1C37542E7B4D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StgSharp.Common", "src\StgSharp.Common\StgSharp.Common.csproj", "{5D646C0E-CCF8-B5B4-7DE8-1C37542E7B4D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/StgSharp.RegularAnalysis/Abstraction/SequenceEmitter.cs b/src/StgSharp.RegularAnalysis/Abstraction/SequenceEmitter.cs index e23e3bf7..c92490ff 100644 --- a/src/StgSharp.RegularAnalysis/Abstraction/SequenceEmitter.cs +++ b/src/StgSharp.RegularAnalysis/Abstraction/SequenceEmitter.cs @@ -48,6 +48,15 @@ namespace StgSharp.RegularAnalysis.Abstraction private readonly Node _head; private Node _tail; + private SequenceEmitter( + Node node + ) + { + _isRoot = true; + _head = node; + _tail = _head; + } + public SequenceEmitter() { _isRoot = true; @@ -57,8 +66,6 @@ namespace StgSharp.RegularAnalysis.Abstraction public int Count { get; private set; } - private static bool IsString { get; } = typeof(T) == typeof(string); - public SequenceEmitter Append( T unit ) @@ -92,6 +99,16 @@ namespace StgSharp.RegularAnalysis.Abstraction return this; } + public SequenceEmitter Clone() + { + if (!_isRoot) { + throw new InvalidOperationException("This emitter has been appended to another emitter. It is now readonly."); + } + SequenceEmitter clone = new(); + Node current = _head; + return clone; + } + public Enumerator GetEnumerator() { return _isRoot ? @@ -173,6 +190,18 @@ namespace StgSharp.RegularAnalysis.Abstraction private sealed class Node { + public Node() + { + IRList = []; + } + + public Node( + int capacity + ) + { + IRList = new(capacity); + } + public T this[ int index ] @@ -185,7 +214,7 @@ namespace StgSharp.RegularAnalysis.Abstraction public int Count => IRList.Count; - public List IRList { get; } = []; + public List IRList { get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add( @@ -195,6 +224,13 @@ namespace StgSharp.RegularAnalysis.Abstraction IRList.Add(ir); } + public void AddRange( + IEnumerable irs + ) + { + IRList.AddRange(irs); + } + } } diff --git a/src/StgSharp.RegularAnalysis/Text/RegexAnalyzer.SourceGen.CharSetEmitter.cs b/src/StgSharp.RegularAnalysis/Text/RegexAnalyzer.SourceGen.CharSetEmitter.cs deleted file mode 100644 index 890bd449..00000000 --- a/src/StgSharp.RegularAnalysis/Text/RegexAnalyzer.SourceGen.CharSetEmitter.cs +++ /dev/null @@ -1,105 +0,0 @@ -// ----------------------------------------------------------------------------- -// file="RegexAnalyzer.SourceGen.CharSetEmitter" -// Project: StgSharp -// Copyright (c) Nitload. -// SPDX-License-Identifier: MIT -// ----------------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace StgSharp.RegularAnalysis.Text -{ - internal enum CharSetType - { - - None, - Single, - Range, - Set - - } - - internal record struct RegexCharSet( - string value, - CharSetType t, - bool accept - ) - { - - public bool IsAcceptable { get; set; } = accept; - - public CharSetType Type { get; set; } = t; - - public string Value { get; set; } = value; - - public override readonly string ToString() - { - return $"{{value:{value}, type:{Type}, accept:{IsAcceptable}}}"; - } - - } - - internal static partial class RegexAnalyzerBackEnd - { - - public static RegexCharSet[] FigureCharSetType( - ReadOnlySpan source - ) - { - // range or single - bool accept; - if (source[0] == '[') - { - int idx; - accept = source[1] != '^'; - idx = accept ? 1 : 2; - ReadOnlySpan seq = source.Slice(idx, source.Length - idx - 1); - if (seq.IndexOf('-') == -1) - { - return [new RegexCharSet(seq.ToString(), CharSetType.Single, accept)]; - } else - { - List list = []; - for (; seq.Length > 0; ) - { - int pos = seq.IndexOf('-'); - if (pos == -1) - { - RegexCharSet single = new(seq.ToString(), CharSetType.Single, accept); - list.Add(single); - break; - } else - if (pos > 1) { - list.Add(new(seq[0..(pos - 1)].ToString(), CharSetType.Single, accept)); - } - list.Add(new($"{seq[pos - 1]}{seq[pos + 1]}", CharSetType.Range, accept)); - seq = seq[(pos + 2)..]; - } - return [.. list]; - } - } else if (source[0] == '\\') - { - // set - accept = char.IsAsciiLetterUpper(source[0]); - return char.ToLower(source[0], CultureInfo.InvariantCulture) - switch - { - 's' => [new("s", CharSetType.Set, accept)], - 'w' => [new("w", CharSetType.Set, accept)], - 'd' => [new("d", CharSetType.Set, accept)], - _ => throw new NotSupportedException() - }; - } else - { - // unknown, throw - throw new InvalidCastException($"Unknown char set: {source}"); - } - } - - } -} diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Diagnostic.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Diagnostic.cs index 69c9e7d5..77f3ddbf 100644 --- a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Diagnostic.cs +++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Diagnostic.cs @@ -24,6 +24,13 @@ namespace StgSharp.RegularAnalysis.Text category:"NGRA.TextRegex", isEnabledByDefault:true); + private static readonly DiagnosticDescriptor CompileFailDiag = new(id:"NGRA005", + title:"Unexpected exception when compiling", + messageFormat:"Unexpected exception handles when compiling expression \"{0}\":{1}", + defaultSeverity:DiagnosticSeverity.Error, + category:"NGRA.TextRegex", + isEnabledByDefault:true); + private static readonly DiagnosticDescriptor IncorrectContainingTypeDiag = new(id:"NGRA005", title:$"Containing type can only be struct or class", messageFormat:$"Containing type: {{0}} is a {{1}}, but not class or struct", diff --git a/src/StgSharp.RegularAnalysis/Text/RegexAnalyzer.SourceGen.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs similarity index 81% rename from src/StgSharp.RegularAnalysis/Text/RegexAnalyzer.SourceGen.cs rename to src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs index 97805e66..add9a863 100644 --- a/src/StgSharp.RegularAnalysis/Text/RegexAnalyzer.SourceGen.cs +++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs @@ -1,26 +1,26 @@ // ----------------------------------------------------------------------------- -// file="RegexAnalyzer.SourceGen" +// file="TextRegexSourceGen.GenClass" // Project: StgSharp // Copyright (c) Nitload. // SPDX-License-Identifier: MIT // ----------------------------------------------------------------------------- -using Microsoft.CodeAnalysis; using StgSharp.RegularAnalysis.Abstraction; using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace StgSharp.RegularAnalysis.Text { - public partial class RegexAnalyzer + internal partial class TextRegexSourceGen { - internal static SequenceEmitter GenerateSource(TextRegexSource source) + internal static SequenceEmitter GenerateSource( + TextRegexSource source + ) { SequenceEmitter se = new(); List> sub_match_list = []; @@ -33,7 +33,7 @@ namespace StgSharp.RegularAnalysis.Text const string current_ptr = "current_ptr"; - _ = se.AppendLine(@"public override MatchResult Match(ReadOnlySpan text)")// + _ = se.AppendLine($@"public override MatchResult Match({ROS_char} text)")// .AppendLine(@"{"); int region_count = info.RegionCount; @@ -51,6 +51,7 @@ namespace StgSharp.RegularAnalysis.Text { int count = int.Min(8, ir_sp.Length - index); ir_sp.Slice(index, count).CopyTo(scan_win); + if (TryGenerateMatch(scan_win, se) > 0) { } } while (index < ir.Count); foreach (SequenceEmitter _sub in sub_match_list) @@ -63,14 +64,17 @@ namespace StgSharp.RegularAnalysis.Text return se; /**/ - int TryGenerateMatch(Span scan_win, SequenceEmitter sb) + int TryGenerateMatch( + Span scan_win, + SequenceEmitter sb + ) { if (scan_win[0] is not RegexMatchSeqIR seq) { return -1; } string pattern = seq.Pattern; int length = pattern.Length; - _ = sb.Append(string.Empty) + _ = sb.AppendLine() .AppendLine($@"if(text[{current_ptr}..({current_ptr} + {length})] == {pattern})") .AppendLine($@"{{") .AppendLine($@"{current_ptr} += {length};") @@ -83,4 +87,3 @@ namespace StgSharp.RegularAnalysis.Text } } - diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs new file mode 100644 index 00000000..01c7ce7d --- /dev/null +++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs @@ -0,0 +1,133 @@ +// ----------------------------------------------------------------------------- +// file="TextRegexSourceGen.GenFile" +// Project: StgSharp +// Copyright (c) Nitload. +// SPDX-License-Identifier: MIT +// ----------------------------------------------------------------------------- + +using Microsoft.CodeAnalysis; +using StgSharp.RegularAnalysis.Abstraction; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.RegularAnalysis.Text +{ + internal partial class TextRegexSourceGen + { + + public const string ROS_char = "global::System.ReadOnlySpan"; + public const string Text_Regex = "global::StgSharp.RegularAnalysis.Text.TextRegex"; + + private static readonly SymbolDisplayFormat TypeSourceFormat = + SymbolDisplayFormat.FullyQualifiedFormat + .AddMiscellaneousOptions( + SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier); + + private static string AsSource() + { + Type t = typeof(T); + return t.IsGenericType ? throw new InvalidOperationException() : $"global::{t.FullName}"; + } + + private static void GenerateRegexSourceFile( + SourceProductionContext context, + TextRegexBinding binding + ) + { + StringBuilder file_name_sb = new(); + SequenceEmitter ce = new(); + SourceRecord gen_source = binding.Source; + TypeSource type = binding.Source.ContainingType; + + _ = file_name_sb.Append(CultureInfo.InvariantCulture, $"{gen_source.NamespaceName}."); + _ = ce.AppendLine($@"// ") + .AppendLine($@"#nullable enable") + .AppendLine($@"using StgSharp.RegularAnalysis.Text;") + .AppendLine($@"using StgSharp.RegularAnalysis.Abstraction;") + .AppendLine($@"using System;") + .AppendLine($@"using System.Text;") + .AppendLine($@"using System.Threading.Tasks;") + .AppendLine() + .AppendLine($@"namespace {gen_source.NamespaceName};"); + + string static_modifier; + + int brace_count = 0; + do + { + _ = file_name_sb.Append(CultureInfo.InvariantCulture, $@"{type.TypeName}."); + string declare_type = type.DeclType switch + { + TypeKind.Class => "class", + TypeKind.Struct => "struct", + _ => throw new InvalidOperationException($"Unexpected type kind: {type.DeclType}"), + }; + static_modifier = type.IsStatic ? "static" : string.Empty; + _ = ce.AppendLine($@"{ToKeyword(type.Accessibility)} {static_modifier} partial {declare_type} {type.TypeName}") + .AppendLine("{"); + brace_count++; + type = type.InnerType!; + } while (type is not null); + + static_modifier = gen_source.IsMethodStatic ? "static" : string.Empty; + _ = ce.AppendLine(@$"{ToKeyword(gen_source.MethodAccessibility)} {static_modifier} {Text_Regex} {gen_source.MethodName}()") + .AppendLine("{") + /**/ //TODO return single instance of the TextRegex object + .AppendLine("}"); + + // TODO inject method source code here + + for (int i = 0; i < brace_count; i++) + { + _ = ce.AppendLine("}"); + } + + StringBuilder code_source = new(); + brace_count = 0; + foreach (string line in ce) + { + bool is_right_brace = line == "}"; + brace_count -= is_right_brace ? 1 : 0; + for (int i = 0; i < brace_count; i++) { + _ = code_source.Append(" "); + } + _ = code_source.AppendLine(line); + brace_count += is_right_brace ? 0 : (line == "{" ? 1 : 0); + } + + _ = file_name_sb.Append(CultureInfo.InvariantCulture, $@"{binding.Source.MethodName}.g.cs"); + string file_name = file_name_sb.ToString(); + context.AddSource(file_name, code_source.ToString()); + + foreach (Diagnostic diag in binding.RegexDiagnostic) { + context.ReportDiagnostic(diag); + } + } + + private static string ToKeyword( + Accessibility accessibility + ) + { + return accessibility switch + { + Accessibility.Public => "public", + Accessibility.Private => "private", + Accessibility.Internal => "internal", + Accessibility.Protected => "protected", + + Accessibility.ProtectedAndInternal => "private protected", + + Accessibility.ProtectedOrInternal => "protected internal", + + _ => throw new InvalidOperationException( + $"Unexpected accessibility: {accessibility}"), + }; + } + + } +} diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Source.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Source.cs index 122058b2..83154cb0 100644 --- a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Source.cs +++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.Source.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using StgSharp.RegularAnalysis.Abstraction; using System; using System.Collections.Generic; using System.Linq; @@ -18,19 +19,21 @@ namespace StgSharp.RegularAnalysis.Text internal partial class TextRegexSourceGen { - private record struct SourceRecord( + private readonly record struct SourceRecord( - bool IsClassStatic, - bool IsMethodStatic, - string Pattern, - string MethodName, - string NamespaceName, - Accessibility MethodAccessibility, - TypeSource ContainingType + bool IsClassStatic, + bool IsMethodStatic, + string Pattern, + string MethodName, + string NamespaceName, + Accessibility MethodAccessibility, + TypeSource ContainingType, + Location PatternDefineLocation ); private sealed record TypeSource( bool IsStatic, + string TypeDisplayName, string TypeName, TypeKind DeclType, Accessibility Accessibility, @@ -46,6 +49,8 @@ namespace StgSharp.RegularAnalysis.Text public bool IsMethodStatic { get; set; } + public Location PatternDefineLocation { get; set; } + public string NameSpaceName { get; set; } public string Pattern { get; set; } @@ -57,7 +62,8 @@ namespace StgSharp.RegularAnalysis.Text public readonly SourceRecord AsRecord() { return new SourceRecord(IsClassStatic, IsMethodStatic, Pattern, MethodName, - NameSpaceName, MethodAccessibility, ContainingType); + NameSpaceName, MethodAccessibility, ContainingType, + PatternDefineLocation); } } @@ -67,10 +73,28 @@ namespace StgSharp.RegularAnalysis.Text private readonly List _diagnostics = []; + private TextRegexBinding( + List diagnostics, + SequenceEmitter generatedSource, + SourceRecord source + ) + { + _diagnostics = diagnostics ?? []; + GeneratedSource = generatedSource ?? new(); + Source = source; + } + + public TextRegexBinding() + { + _diagnostics = []; + } + public bool IsValid { get; private set; } = true; public IReadOnlyList RegexDiagnostic => _diagnostics; + public SequenceEmitter GeneratedSource { get; set; } + public SourceRecord Source { get; set; } public void AddDiagnostic( @@ -89,16 +113,15 @@ namespace StgSharp.RegularAnalysis.Text { Diagnostic diag = Diagnostic.Create(descriptor, location, messageArgs); _diagnostics.Add(diag); - IsValid = IsValid && (diag.DefaultSeverity != DiagnosticSeverity.Error); + IsValid = IsValid && (diag.Severity != DiagnosticSeverity.Error); } public TextRegexBinding Clone() { - TextRegexBinding binding = new() - { - IsValid = this.IsValid, - }; - binding._diagnostics.AddRange(this._diagnostics); + SequenceEmitter code = GeneratedSource.Clone(); + List diag = new(_diagnostics.Count); + diag.AddRange(this._diagnostics); + TextRegexBinding binding = new(diag, code, Source with { }); return binding; } diff --git a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.cs b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.cs index 848390c5..5dd47e2f 100644 --- a/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.cs +++ b/src/StgSharp.RegularAnalysis/Text/TextRegexSourceGen.cs @@ -8,10 +8,12 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using StgSharp.RegularAnalysis.Abstraction; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Security.AccessControl; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -21,7 +23,7 @@ namespace StgSharp.RegularAnalysis.Text internal partial class TextRegexSourceGen : IIncrementalGenerator { - private static readonly string TextRegexTypeName = typeof(TextRegex).FullName ?? + private static readonly string TextRegexTypeName = typeof(TextRegexAttribute).FullName ?? string.Empty; public void Initialize( @@ -37,6 +39,12 @@ namespace StgSharp.RegularAnalysis.Text ) => true, BindTextRegexCandidate); IncrementalValuesProvider match = RegisterDiagnosticBypass(context, provider); + + IncrementalValuesProvider compile = match.Select(CompileRegexMethodSource); + + IncrementalValuesProvider compile_success = RegisterDiagnosticBypass(context, compile); + + context.RegisterSourceOutput(compile_success, GenerateRegexSourceFile); } private static TextRegexBinding BindTextRegexCandidate( @@ -84,7 +92,7 @@ namespace StgSharp.RegularAnalysis.Text INamedTypeSymbol contain = method_symbol.ContainingType; INamespaceSymbol namespace_symbol = contain.ContainingNamespace; - TypeSource type_source = null; + TypeSource type_source = null!; while (contain is not null) { @@ -98,22 +106,53 @@ namespace StgSharp.RegularAnalysis.Text if (!bind.IsValid) { return bind; } - TypeSource t = new(contain.IsStatic, contain.Name, contain.TypeKind, + string display = contain.ToDisplayString(TypeSourceFormat); + TypeSource t = new(contain.IsStatic, display, contain.Name, contain.TypeKind, contain.DeclaredAccessibility, type_source); type_source = t; - contain = contain.BaseType!; + contain = contain.ContainingType!; } Source s = new() { MethodName = method_symbol.Name, - NameSpaceName = namespace_symbol.Name, + NameSpaceName = namespace_symbol.ToDisplayString(), + PatternDefineLocation = method_decl.GetLocation(), + IsMethodStatic = method_decl.Modifiers.Any(SyntaxKind.StaticKeyword), + ContainingType = type_source, + MethodAccessibility = method_symbol.DeclaredAccessibility, }; - + foreach (KeyValuePair item in attribute.NamedArguments) + { + if (item.Key == nameof(TextRegexAttribute.Pattern)) { + s.Pattern = item.Value.Value as string ?? string.Empty; + } + } bind.Source = s.AsRecord(); return bind; } + private static TextRegexBinding CompileRegexMethodSource( + TextRegexBinding source, + CancellationToken ct + ) + { + ct.ThrowIfCancellationRequested(); + TextRegexBinding result = source.Clone(); + string pattern = result.Source.Pattern; + TextRegexSource analyze_result = RegexAnalyzer.Analyze(pattern); + if (analyze_result.AnalyseException is not null) + { + result.AddDiagnostic(CompileFailDiag, null, analyze_result.AnalyseException.Message); + } else + { + SequenceEmitter method_source = GenerateSource(analyze_result); + result.GeneratedSource = method_source; + } + + return result; + } + private static IncrementalValuesProvider RegisterDiagnosticBypass( IncrementalGeneratorInitializationContext context, IncrementalValuesProvider bindings diff --git a/src/StgSharp.GenerateGL/CodeGen/CsTypeMapper.cs b/test/StgSharp.GenerateGL/CodeGen/CsTypeMapper.cs similarity index 100% rename from src/StgSharp.GenerateGL/CodeGen/CsTypeMapper.cs rename to test/StgSharp.GenerateGL/CodeGen/CsTypeMapper.cs diff --git a/src/StgSharp.GenerateGL/CodeGen/Generator.cs b/test/StgSharp.GenerateGL/CodeGen/Generator.cs similarity index 100% rename from src/StgSharp.GenerateGL/CodeGen/Generator.cs rename to test/StgSharp.GenerateGL/CodeGen/Generator.cs diff --git a/src/StgSharp.GenerateGL/CodeGen/GlXmlParser.cs b/test/StgSharp.GenerateGL/CodeGen/GlXmlParser.cs similarity index 100% rename from src/StgSharp.GenerateGL/CodeGen/GlXmlParser.cs rename to test/StgSharp.GenerateGL/CodeGen/GlXmlParser.cs diff --git a/src/StgSharp.GenerateGL/CodeGen/Models.cs b/test/StgSharp.GenerateGL/CodeGen/Models.cs similarity index 100% rename from src/StgSharp.GenerateGL/CodeGen/Models.cs rename to test/StgSharp.GenerateGL/CodeGen/Models.cs diff --git a/src/StgSharp.GenerateGL/Docs/SourceGenerator.md b/test/StgSharp.GenerateGL/Docs/SourceGenerator.md similarity index 100% rename from src/StgSharp.GenerateGL/Docs/SourceGenerator.md rename to test/StgSharp.GenerateGL/Docs/SourceGenerator.md diff --git a/src/StgSharp.GenerateGL/GenerateGL.csproj b/test/StgSharp.GenerateGL/GenerateGL.csproj similarity index 100% rename from src/StgSharp.GenerateGL/GenerateGL.csproj rename to test/StgSharp.GenerateGL/GenerateGL.csproj diff --git a/src/StgSharp.GenerateGL/Program.cs b/test/StgSharp.GenerateGL/Program.cs similarity index 100% rename from src/StgSharp.GenerateGL/Program.cs rename to test/StgSharp.GenerateGL/Program.cs diff --git a/src/StgSharp.GenerateGL/gl.h b/test/StgSharp.GenerateGL/gl.h similarity index 100% rename from src/StgSharp.GenerateGL/gl.h rename to test/StgSharp.GenerateGL/gl.h diff --git a/src/StgSharp.GenerateGL/xml/Genglvnd b/test/StgSharp.GenerateGL/xml/Genglvnd similarity index 100% rename from src/StgSharp.GenerateGL/xml/Genglvnd rename to test/StgSharp.GenerateGL/xml/Genglvnd diff --git a/src/StgSharp.GenerateGL/xml/README.adoc b/test/StgSharp.GenerateGL/xml/README.adoc similarity index 100% rename from src/StgSharp.GenerateGL/xml/README.adoc rename to test/StgSharp.GenerateGL/xml/README.adoc diff --git a/src/StgSharp.GenerateGL/xml/genglvnd.py b/test/StgSharp.GenerateGL/xml/genglvnd.py similarity index 100% rename from src/StgSharp.GenerateGL/xml/genglvnd.py rename to test/StgSharp.GenerateGL/xml/genglvnd.py diff --git a/src/StgSharp.GenerateGL/xml/genheaders.py b/test/StgSharp.GenerateGL/xml/genheaders.py similarity index 100% rename from src/StgSharp.GenerateGL/xml/genheaders.py rename to test/StgSharp.GenerateGL/xml/genheaders.py diff --git a/src/StgSharp.GenerateGL/xml/gl.xml b/test/StgSharp.GenerateGL/xml/gl.xml similarity index 100% rename from src/StgSharp.GenerateGL/xml/gl.xml rename to test/StgSharp.GenerateGL/xml/gl.xml diff --git a/src/StgSharp.GenerateGL/xml/glx.xml b/test/StgSharp.GenerateGL/xml/glx.xml similarity index 100% rename from src/StgSharp.GenerateGL/xml/glx.xml rename to test/StgSharp.GenerateGL/xml/glx.xml diff --git a/src/StgSharp.GenerateGL/xml/glxproto.reserved.txt b/test/StgSharp.GenerateGL/xml/glxproto.reserved.txt similarity index 100% rename from src/StgSharp.GenerateGL/xml/glxproto.reserved.txt rename to test/StgSharp.GenerateGL/xml/glxproto.reserved.txt diff --git a/src/StgSharp.GenerateGL/xml/readme.pdf b/test/StgSharp.GenerateGL/xml/readme.pdf similarity index 100% rename from src/StgSharp.GenerateGL/xml/readme.pdf rename to test/StgSharp.GenerateGL/xml/readme.pdf diff --git a/src/StgSharp.GenerateGL/xml/readme.tex b/test/StgSharp.GenerateGL/xml/readme.tex similarity index 100% rename from src/StgSharp.GenerateGL/xml/readme.tex rename to test/StgSharp.GenerateGL/xml/readme.tex diff --git a/src/StgSharp.GenerateGL/xml/reg.py b/test/StgSharp.GenerateGL/xml/reg.py similarity index 100% rename from src/StgSharp.GenerateGL/xml/reg.py rename to test/StgSharp.GenerateGL/xml/reg.py diff --git a/src/StgSharp.GenerateGL/xml/registry.rnc b/test/StgSharp.GenerateGL/xml/registry.rnc similarity index 100% rename from src/StgSharp.GenerateGL/xml/registry.rnc rename to test/StgSharp.GenerateGL/xml/registry.rnc diff --git a/src/StgSharp.GenerateGL/xml/testesext.c b/test/StgSharp.GenerateGL/xml/testesext.c similarity index 100% rename from src/StgSharp.GenerateGL/xml/testesext.c rename to test/StgSharp.GenerateGL/xml/testesext.c diff --git a/src/StgSharp.GenerateGL/xml/testglext.c b/test/StgSharp.GenerateGL/xml/testglext.c similarity index 100% rename from src/StgSharp.GenerateGL/xml/testglext.c rename to test/StgSharp.GenerateGL/xml/testglext.c diff --git a/src/StgSharp.GenerateGL/xml/vendors.txt b/test/StgSharp.GenerateGL/xml/vendors.txt similarity index 100% rename from src/StgSharp.GenerateGL/xml/vendors.txt rename to test/StgSharp.GenerateGL/xml/vendors.txt diff --git a/src/StgSharp.GenerateGL/xml/wgl.xml b/test/StgSharp.GenerateGL/xml/wgl.xml similarity index 100% rename from src/StgSharp.GenerateGL/xml/wgl.xml rename to test/StgSharp.GenerateGL/xml/wgl.xml diff --git a/src/StgSharp.GenerateGL/xml/wgltypes.txt b/test/StgSharp.GenerateGL/xml/wgltypes.txt similarity index 100% rename from src/StgSharp.GenerateGL/xml/wgltypes.txt rename to test/StgSharp.GenerateGL/xml/wgltypes.txt