-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
123 additions
and
1 deletion.
There are no files selected for viewing
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
108 changes: 108 additions & 0 deletions
108
ReactWithDotNet.SourceGenerator/HasValueMethodGenerator.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,108 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Text; | ||
|
||
namespace ReactWithDotNet; | ||
|
||
[Generator] | ||
public class HasValueMethodGenerator : ISourceGenerator | ||
Check warning on line 12 in ReactWithDotNet.SourceGenerator/HasValueMethodGenerator.cs GitHub Actions / build
Check warning on line 12 in ReactWithDotNet.SourceGenerator/HasValueMethodGenerator.cs GitHub Actions / build
|
||
{ | ||
public void Execute(GeneratorExecutionContext context) | ||
{ | ||
if (context.SyntaxReceiver is not SyntaxReceiver receiver) | ||
{ | ||
return; | ||
} | ||
|
||
// Loop through collected classes | ||
foreach (var classDeclaration in receiver.CandidateClasses) | ||
{ | ||
// Get the class name | ||
var className = classDeclaration.Identifier.Text; | ||
|
||
var lines = new List<string> | ||
{ | ||
$"namespace {GetNamespace(classDeclaration)};", | ||
|
||
$"static class {className}HasValueChecker", | ||
"{", | ||
$" public static bool HasValue({className} value)", | ||
" {", | ||
" if(value == null)", | ||
" {", | ||
" return false;", | ||
" }" | ||
}; | ||
|
||
foreach (var member in classDeclaration.Members) | ||
{ | ||
if (member is PropertyDeclarationSyntax propertyDeclarationSyntax) | ||
{ | ||
var propertyTypeName = propertyDeclarationSyntax.Type.ToFullString().Trim(); | ||
var propertyName = propertyDeclarationSyntax.Identifier.ValueText; | ||
|
||
if (propertyTypeName == "double?"|| propertyTypeName == "bool?") | ||
{ | ||
lines.Add($"if (value.{propertyName}.HasValue)"); | ||
lines.Add(" return true;"); | ||
continue; | ||
} | ||
|
||
|
||
} | ||
} | ||
|
||
lines.Add(" return false;"); | ||
lines.Add(" }"); // close method | ||
lines.Add("}"); // close class | ||
|
||
context.AddSource($"{className}HasValueChecker.generated", SourceText.From(string.Join(Environment.NewLine, lines), Encoding.UTF8)); | ||
} | ||
} | ||
|
||
public void Initialize(GeneratorInitializationContext context) | ||
{ | ||
// AttachToDebugger(); | ||
|
||
// Register a syntax receiver to collect classes with the custom attribute | ||
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); | ||
} | ||
|
||
// Helper to extract namespace | ||
static string GetNamespace(ClassDeclarationSyntax classDeclaration) | ||
{ | ||
var fileScopedNamespaceName = classDeclaration.FirstAncestorOrSelf<FileScopedNamespaceDeclarationSyntax>()?.Name; | ||
if (fileScopedNamespaceName != null) | ||
{ | ||
return fileScopedNamespaceName.ToString(); | ||
} | ||
|
||
var namespaceDeclaration = classDeclaration.Ancestors() | ||
.OfType<NamespaceDeclarationSyntax>() | ||
.FirstOrDefault(); | ||
|
||
return namespaceDeclaration?.Name.ToString() ?? "global"; | ||
} | ||
|
||
class SyntaxReceiver : ISyntaxReceiver | ||
{ | ||
public List<ClassDeclarationSyntax> CandidateClasses { get; } = new(); | ||
|
||
// Called for every syntax node in the compilation, we gather candidates here | ||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode) | ||
{ | ||
// Check if the node is a class declaration with the [AddExtraProperties] attribute | ||
if (syntaxNode is ClassDeclarationSyntax classDeclaration && | ||
classDeclaration.AttributeLists | ||
.SelectMany(al => al.Attributes) | ||
.Any(ad => ad.Name.ToString() == "GenerateHasValue")) | ||
{ | ||
CandidateClasses.Add(classDeclaration); | ||
} | ||
} | ||
} | ||
} |
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