Skip to content

Commit 444629b

Browse files
authored
Merge pull request #86 from bj-rn/feat/routed-events
BREAKING: Feat/routed events
2 parents ace44d0 + fa5d058 commit 444629b

20 files changed

Lines changed: 1741 additions & 80 deletions

Directory.Build.props

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<Project>
2+
<PropertyGroup>
3+
<VLVersion>2025.7.1-0116-gaeae322323</VLVersion>
4+
<AvaloniaVersion>11.2.1</AvaloniaVersion>
5+
<StrideVersion>4.2.0.2293</StrideVersion>
6+
</PropertyGroup>
7+
</Project>

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ nuget install VL.Avalonia.Stride
3131
nuget install VL.Avalonia.Custom
3232
```
3333

34-
Works with `vvvv_gamma >= 7.0`
34+
## Compatibility
35+
36+
| Version | vvvv gamma Version |
37+
| :--- | :--- |
38+
| `v0.4.X` | >= `7.1-0116` |
39+
| `v0.3.1` - `v0.3.16` | `7.0` |
40+
| `v0.3.0`| `7.0-xxxx`, `6.9` |
41+
3542

3643
## How-to
3744

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using Microsoft.CodeAnalysis;
3+
using VL.Avalonia.CodeGen.Forwards;
4+
5+
namespace VL.Avalonia.CodeGen
6+
{
7+
[Generator]
8+
public class AvaloniaReflectionGenerator : IIncrementalGenerator
9+
{
10+
const string RESTRICTED_ASSEMBLY_NAME = "VL.Avalonia";
11+
12+
public void Initialize(IncrementalGeneratorInitializationContext context)
13+
{
14+
var compilationProvider = context.CompilationProvider;
15+
16+
context.RegisterSourceOutput(
17+
compilationProvider,
18+
(spc, compilation) =>
19+
{
20+
// We want to generate only for VL.Avalonia assembly
21+
if (compilation.AssemblyName != RESTRICTED_ASSEMBLY_NAME)
22+
return;
23+
24+
try
25+
{
26+
RoutedEventArgsGenerator.Generate(spc, compilation);
27+
RoutedEventGenerator.Generate(spc, compilation);
28+
}
29+
catch (Exception ex) { }
30+
}
31+
);
32+
}
33+
}
34+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Text;
4+
using Microsoft.CodeAnalysis;
5+
using Microsoft.CodeAnalysis.Text;
6+
7+
namespace VL.Avalonia.CodeGen.Forwards
8+
{
9+
public static class RoutedEventArgsGenerator
10+
{
11+
const string TARGET_FILENAME = "RoutedEventArgsForwards.g.cs";
12+
const string TARGET_TYPE_NAME = "Avalonia.Interactivity.RoutedEventArgs";
13+
14+
public static void Generate(SourceProductionContext spc, Compilation compilation)
15+
{
16+
var routedEventArgsType = compilation.GetTypeByMetadataName(TARGET_TYPE_NAME);
17+
if (routedEventArgsType == null)
18+
return;
19+
20+
var foundTypes = new List<INamedTypeSymbol>();
21+
22+
foreach (var reference in compilation.SourceModule.ReferencedAssemblySymbols)
23+
{
24+
if (!reference.Name.StartsWith("Avalonia"))
25+
continue;
26+
27+
// Helper function to visit all types in the assembly
28+
VisitNamespace(reference.GlobalNamespace, routedEventArgsType, foundTypes);
29+
}
30+
31+
if (foundTypes.Count == 0)
32+
{
33+
return;
34+
}
35+
36+
foundTypes.Add(routedEventArgsType);
37+
38+
var namespaces = foundTypes
39+
.Select(t => t.ContainingNamespace.ToDisplayString())
40+
.Distinct()
41+
.OrderBy(n => n);
42+
43+
var sb = new StringBuilder();
44+
45+
sb.AppendLine("using System;");
46+
sb.AppendLine("using VL.Core.Import;");
47+
48+
foreach (var ns in namespaces)
49+
{
50+
sb.AppendLine($"using {ns};");
51+
}
52+
sb.AppendLine();
53+
54+
var typeFormat = SymbolDisplayFormat.MinimallyQualifiedFormat;
55+
56+
foreach (var type in foundTypes)
57+
{
58+
sb.AppendLine(
59+
// csharpier-ignore
60+
$@"[assembly: ImportType(typeof({type.ToDisplayString(typeFormat)}), Category = ""{type.ContainingNamespace.ToDisplayString()}"")]"
61+
);
62+
}
63+
64+
spc.AddSource(TARGET_FILENAME, SourceText.From(sb.ToString(), Encoding.UTF8));
65+
}
66+
67+
private static void VisitNamespace(
68+
INamespaceSymbol namespaceSymbol,
69+
INamedTypeSymbol baseType,
70+
List<INamedTypeSymbol> foundTypes
71+
)
72+
{
73+
foreach (var member in namespaceSymbol.GetMembers())
74+
{
75+
if (member is INamespaceSymbol nestedNs)
76+
{
77+
VisitNamespace(nestedNs, baseType, foundTypes);
78+
}
79+
else if (member is INamedTypeSymbol typeSymbol)
80+
{
81+
if (
82+
typeSymbol.TypeKind == TypeKind.Class
83+
&& !typeSymbol.IsAbstract
84+
&& InheritsFrom(typeSymbol, baseType)
85+
)
86+
{
87+
foundTypes.Add(typeSymbol);
88+
}
89+
}
90+
}
91+
}
92+
93+
private static bool InheritsFrom(INamedTypeSymbol type, INamedTypeSymbol baseType)
94+
{
95+
var current = type.BaseType;
96+
while (current != null)
97+
{
98+
if (SymbolEqualityComparer.Default.Equals(current, baseType))
99+
return true;
100+
current = current.BaseType;
101+
}
102+
return false;
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)