Skip to content

Commit

Permalink
first implementation for Non-rendered layers
Browse files Browse the repository at this point in the history
  • Loading branch information
Aytackydln committed Oct 31, 2024
1 parent 4f31502 commit b2ce80d
Show file tree
Hide file tree
Showing 87 changed files with 1,845 additions and 1,109 deletions.
3 changes: 1 addition & 2 deletions Project-Aurora/AuroraCommon/Utils/CommonColorUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public static Color AddColors(in Color background, in Color foreground)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Color AddColors(in Color background, in Color foreground, ref Color resultCache)
public static ref Color AddColors(ref readonly Color background, ref readonly Color foreground, ref Color resultCache)
{
var foreA = foreground.A;
var backA = background.A;
Expand Down Expand Up @@ -347,7 +347,6 @@ public static Color FastColorTransparent(byte r, byte g, byte b)
return FastColor((byte)(r * normalizer), (byte)(g * normalizer), (byte)(b * normalizer), brightness);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Color FastColor(byte r, byte g, byte b, byte a = 255)
{
return Color.FromArgb(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.0"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0"/>
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using Microsoft.CodeAnalysis;

namespace AuroraSourceGenerator;

public static class ClassUtils
{
public static IEnumerable<INamedTypeSymbol> GetBaseTypes(INamedTypeSymbol type)
{
var currentType = type;
while (currentType != null)
{
yield return currentType;
currentType = currentType.BaseType;
}
}

public static IEnumerable<ITypeSymbol> GetBaseTypes(ITypeSymbol type)
{
var currentType = type;
while (currentType != null)
{
yield return currentType;
currentType = currentType.BaseType;
}
}

public static IEnumerable<ITypeSymbol> GetAllInterfaces(ITypeSymbol type)
{
return type.AllInterfaces;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace System.Runtime.CompilerServices;

public class IsExternalInit;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
Expand All @@ -15,71 +16,89 @@ internal class PropertyAccess(string gsiPath, string accessPath)
public string AccessPath { get; } = accessPath;
}

/// <summary>
/// A sample source generator that creates C# classes based on the text file (in this case, Domain Driven Design ubiquitous language registry).
/// When using a simple text file as a baseline, we can create a non-incremental source generator.
/// </summary>
[Generator]
public class NodePropertySourceGenerator : ISourceGenerator
public class NodePropertySourceGenerator : IIncrementalGenerator
{
public void Initialize(GeneratorInitializationContext context)
private const string GameStateInterface = "AuroraRgb.Profiles.GameState";

public void Initialize(IncrementalGeneratorInitializationContext context)
{
// No initialization required for this example
// Get all class declarations from syntax
IncrementalValuesProvider<ClassDeclarationSyntax> classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (s, _) => IsSyntaxTargetForGeneration(s),
transform: static (ctx, _) => GetSemanticTargetForGeneration(ctx))
.Where(static m => m is not null)!;

// Combine the compilation and the class declarations
IncrementalValueProvider<(Compilation Compilation, ImmutableArray<ClassDeclarationSyntax> Classifications)> compilationAndClasses
= context.CompilationProvider.Combine(classDeclarations.Collect());

// Generate the source
context.RegisterSourceOutput(compilationAndClasses,
static (spc, source) => Execute(source.Compilation, source.Classifications, spc));
}

public void Execute(GeneratorExecutionContext context)
private static bool IsSyntaxTargetForGeneration(SyntaxNode node)
=> node is ClassDeclarationSyntax classDeclaration
&& classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword);

private static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context)
{
const string gamestate = "AuroraRgb.Profiles.GameState";
HashSet<string> ignore = [gamestate];

var compilation = context.Compilation;
var classDeclaration = (ClassDeclarationSyntax)context.Node;

// Retrieve the interface symbol
var gameStateInterface = compilation.GetTypeByMetadataName(gamestate);
// Get the semantic model
var semanticModel = context.SemanticModel;
var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration);

if (gameStateInterface == null)
{
// Interface not found, do nothing
return;
}
if (classSymbol == null) return null;

// Check if it's an Aurora class and derives from GameState
if (!IsAuroraClass(classSymbol)) return null;

var gameStateInterface = semanticModel.Compilation.GetTypeByMetadataName(GameStateInterface);
if (gameStateInterface == null) return null;

if (!IsSubtypeOf(classSymbol, gameStateInterface)) return null;

// Find all classes in the compilation
var classes = compilation.SyntaxTrees
.SelectMany(syntaxTree => syntaxTree.GetRoot().DescendantNodes())
.OfType<ClassDeclarationSyntax>()
.Select(declaration => ModelExtensions.GetDeclaredSymbol(compilation.GetSemanticModel(declaration.SyntaxTree), declaration))
.OfType<INamedTypeSymbol>()
.Where(IsAuroraClass)
.Where(IsSubtypeOf(gameStateInterface))
.Where(IsPartialClass)
.Where(classSymbol => !ignore.Contains(classSymbol.ToDisplayString()));

foreach (var classSymbol in classes)
return classDeclaration;
}

private static void Execute(Compilation compilation, ImmutableArray<ClassDeclarationSyntax> classes, SourceProductionContext context)
{
if (classes.IsDefaultOrEmpty) return;

HashSet<string> ignore = [GameStateInterface];

foreach (var classDeclaration in classes)
{
var semanticModel = compilation.GetSemanticModel(classDeclaration.SyntaxTree);
var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration);

if (classSymbol == null) continue;
if (ignore.Contains(classSymbol.ToDisplayString())) continue;

GenerateClassProperties(context, classSymbol);
}
}

private static Func<INamedTypeSymbol, bool> IsSubtypeOf(INamedTypeSymbol gameStateInterface)
private static bool IsSubtypeOf(INamedTypeSymbol classSymbol, INamedTypeSymbol gameStateInterface)
{
return classSymbol =>
var currentType = classSymbol.BaseType;
while (currentType != null)
{
var currentType = classSymbol.BaseType;
while (currentType != null)
if (SymbolEqualityComparer.Default.Equals(currentType, gameStateInterface))
{
if (SymbolEqualityComparer.Default.Equals(currentType, gameStateInterface))
{
return true;
}
currentType = currentType.BaseType;
return true;
}

return false;
};
currentType = currentType.BaseType;
}

return false;
}

private static void GenerateClassProperties(GeneratorExecutionContext context, INamedTypeSymbol classSymbol)
private static void GenerateClassProperties(SourceProductionContext context, INamedTypeSymbol classSymbol)
{
// Get all properties of the class
var properties = GetClassProperties("", classSymbol, $"(({classSymbol.Name})t).");
Expand All @@ -106,14 +125,10 @@ public partial class {{classSymbol.Name}}
}
""";

// Add the generated source to the compilation
context.AddSource(classSymbol.Name + ".g.cs", SourceText.From(source, Encoding.UTF8));
}

private static Func<PropertyAccess, string> Selector()
{
return AccessorMethodSource;
}
private static Func<PropertyAccess, string> Selector() => AccessorMethodSource;

private static string AccessorMethodSource(PropertyAccess valueTuple)
{
Expand All @@ -123,7 +138,7 @@ private static string AccessorMethodSource(PropertyAccess valueTuple)

private static IEnumerable<PropertyAccess> GetClassProperties(string currentPath, INamedTypeSymbol type, string upperAccessPath)
{
var namedTypeSymbols = GetBaseTypes(type);
var namedTypeSymbols = ClassUtils.GetBaseTypes(type);
foreach (var currentType in namedTypeSymbols)
{
foreach (var member in currentType.GetMembers())
Expand All @@ -139,21 +154,19 @@ private static IEnumerable<PropertyAccess> GetClassProperties(string currentPath
var propertyType = property.Type;

var accessPath = property.IsStatic ? GetStaticAccessPath(currentType, property) : upperAccessPath + property.Name;

// Check if the type is a primitive type

if (propertyType.IsValueType || propertyType.SpecialType == SpecialType.System_String)
{
yield return new PropertyAccess(currentPath + property.Name, accessPath);
continue;
}
// Check if the type is a class

if (propertyType.TypeKind is not (TypeKind.Class or TypeKind.Interface)) continue;

var namedTypeSymbol = (INamedTypeSymbol)property.Type;
if (!IsAuroraClass(namedTypeSymbol))
continue;
// prevent infinite recursions, this should look for all previous types actually

if (SymbolEqualityComparer.Default.Equals(namedTypeSymbol, currentType))
{
continue;
Expand All @@ -163,56 +176,21 @@ private static IEnumerable<PropertyAccess> GetClassProperties(string currentPath

var s = property.NullableAnnotation == NullableAnnotation.Annotated ? "?." : ".";
var lowerAccessPath = property.IsStatic ? GetStaticAccessPath(currentType, property) : upperAccessPath + property.Name + s;

foreach (var classProperty in GetClassProperties(upperProperty, namedTypeSymbol, lowerAccessPath))
{
yield return classProperty;
}
}
}

}

private static IEnumerable<INamedTypeSymbol> GetBaseTypes(INamedTypeSymbol type)
{
var currentType = type;
while (currentType != null)
{
yield return currentType;
currentType = currentType.BaseType;
}
}

private static bool IgnoredAttribute(AttributeData arg)
{
return arg.AttributeClass?.Name == "GameStateIgnoreAttribute";
}
=> arg.AttributeClass?.Name == "GameStateIgnoreAttribute";

private static string GetStaticAccessPath(INamedTypeSymbol currentType, IPropertySymbol property)
{
return currentType.ContainingNamespace + "." + currentType.Name + "." + property.Name + ".";
}
=> currentType.ContainingNamespace + "." + currentType.Name + "." + property.Name + ".";

private static bool IsAuroraClass(INamedTypeSymbol namedTypeSymbol)
{
return namedTypeSymbol.ToString().StartsWith("AuroraRgb.");
}

private static bool IsPartialClass(INamedTypeSymbol namedTypeSymbol)
{
// Loop through all the declaration syntax references
foreach (var syntaxNode in namedTypeSymbol.DeclaringSyntaxReferences.Select(syntaxReference => syntaxReference.GetSyntax()))
{
// Check if the syntax node is a class declaration
if (syntaxNode is not ClassDeclarationSyntax classDeclaration) continue;
// Check if the class declaration has the 'partial' modifier
if (classDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword))
{
return true;
}
}

// If no 'partial' modifier is found, return false
return false;
}
=> namedTypeSymbol.ToString().StartsWith("AuroraRgb.");
}
Loading

0 comments on commit b2ce80d

Please sign in to comment.