Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5732971
Add Aspid.Generators.Helper
Oct 27, 2025
6d3f0b2
Fix Bug and add launchSettings.json
Oct 27, 2025
435d9c7
Fix Generate Generic Enum And Struct
Nov 26, 2025
40c56d4
Merge pull request #8 from VPDPersonal/Bug/Fix-Generate-Generic-Enum-…
Nov 26, 2025
b69deec
Fix Size dll
Nov 26, 2025
39b9fc0
Reset fix dll size
Nov 27, 2025
292d96a
Refactor
Dec 2, 2025
d2ed638
Refactor
Dec 2, 2025
62dff38
Refactor BindableCommand
Dec 2, 2025
9d3105f
Refactor BindableField
Dec 3, 2025
02579a5
Add #region in generated code
Dec 3, 2025
299385b
Add support for property
Dec 20, 2025
e4cdf1c
Upgrade Bindable Property generated
Dec 22, 2025
698f3df
Add Invocation PropertyChanged Generator support
Dec 22, 2025
b4aa94f
Add Samples
Dec 22, 2025
207c575
Merge pull request #9 from VPDPersonal/Feature/Add-Bindable-Propertie…
Dec 22, 2025
ca51334
Add public void NotifyCanExecuteChanged() for ViewModel
Jan 12, 2026
55f0232
Merge pull request #10 from VPDPersonal/Feature/Add-NotifyCanExecuteC…
Jan 12, 2026
b31dcb0
Fix NotifyCanExecuteChanged Generated
Jan 18, 2026
f685c8a
Merge pull request #11 from VPDPersonal/Bug/Fix-NotifyCanExecuteChang…
Jan 18, 2026
60e6223
Add Keyword For Set Methods and Refactor
VPDPersonal Jan 22, 2026
dec2969
Remove .this in bindable properties
VPDPersonal Jan 22, 2026
88f73cb
Fix Generated const and properties
VPDPersonal Jan 22, 2026
9ab5f87
Merge pull request #12 from VPDPersonal/Feature/Add-Keyword-For-Fields
VPDPersonal Jan 22, 2026
7cf0832
Merge branch 'main' into Version/Aspid.MVVM-1.1.0
VPDPersonal Feb 3, 2026
a1bc4de
Fix name for bindable properties and add IAnyBinder BinderlLog support
VPDPersonal Feb 22, 2026
640009d
Fix BindAlso
VPDPersonal Feb 24, 2026
a1b0219
Update Aspid.Generators.Helper
VPDPersonal Mar 5, 2026
2f37205
Pass owner and bindable Id to BindSafely/UnbindSafely
VPDPersonal Apr 20, 2026
efb01e2
Skip owner/Id args for single-binder BindSafely emission
VPDPersonal Apr 20, 2026
4ed04b4
Always emit owner/Id args for BindSafely/UnbindSafely
VPDPersonal Apr 20, 2026
16cdf52
Add virtual binder fields generation with HeaderGroup support
VPDPersonal May 22, 2026
5a38b63
Merge pull request #13 from VPDPersonal/Feature/Add-Virtual-Binder-Fi…
VPDPersonal May 22, 2026
5aa2d13
Update Unity copy path to Aspid/MVVM after folder move
VPDPersonal May 22, 2026
c89b151
Merge pull request #15 from VPDPersonal/Refactor/Move-MVVM-Folder
VPDPersonal May 22, 2026
c151e2c
fix(build): glob Source paths in Generators.Sample after package move
VPDPersonal May 30, 2026
4809f9a
build(ci): exclude Generators.Sample from headless solution build
VPDPersonal May 30, 2026
56d5451
Merge pull request #16 from VPDPersonal/fix/sample-csproj-asset-paths
VPDPersonal May 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/

# Debug artifacts
launchSettings.json

# Prevent accidental re-checkin of NuGet.exe
NuGet.exe

Expand Down
2 changes: 0 additions & 2 deletions Aspid.MVVM.Generators.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ Global
{8396B53C-70A1-422E-9E40-9AEBB223F6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8396B53C-70A1-422E-9E40-9AEBB223F6B3}.Release|Any CPU.Build.0 = Release|Any CPU
{A1DE8BA3-CAEC-4823-99D1-720059565792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1DE8BA3-CAEC-4823-99D1-720059565792}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1DE8BA3-CAEC-4823-99D1-720059565792}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1DE8BA3-CAEC-4823-99D1-720059565792}.Release|Any CPU.Build.0 = Release|Any CPU
{837E3102-786A-44C6-9490-1C77BE8D26C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{837E3102-786A-44C6-9490-1C77BE8D26C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{837E3102-786A-44C6-9490-1C77BE8D26C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
Expand All @@ -14,4 +14,15 @@
<None Remove="DDD.UbiquitousLanguageRegistry.txt"/>
</ItemGroup>

<!--
Compile the entire Unity-independent core (Assets/Aspid/MVVM/Source) so the
source generator runs over it. A recursive glob is used instead of an explicit
file list so the project stays in sync as Source files are added/removed/renamed.
-->
<ItemGroup>
<Compile Include="..\..\..\Aspid.MVVM\Assets\Aspid\MVVM\Source\**\*.cs">
<Link>Source\%(RecursiveDir)%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace Aspid.MVVM.Generators.Sample;

[ViewModel]
public partial class ExProperty1Vm
{
private string _firstName = string.Empty;
private string _lastName = string.Empty;

[Bind]
public string FirstName
{
get => _firstName;
private set
{
if (SetFirstNameField(ref _firstName, value))
OnFullNamePropertyChanged();
}
}

[Bind]
[BindAlso(nameof(FullName))]
public string LastName
{
get => _lastName;
private set
{
if (_lastName == value) return;

_lastName = value;
OnLastNamePropertyChanged();
}
}

[Bind]
public string FullName => $"{FirstName} {LastName}";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace Aspid.MVVM.Generators.Sample;

[ViewModel]
public partial class ExProperty2Vm
{
private string _firstName = string.Empty;
private string _lastName = string.Empty;

[Bind]
public string FirstName
{
get => _firstName;
private set
{
if (SetField(ref _firstName, value))
OnPropertyChanged(nameof(FullName));
}
}

[Bind]
[BindAlso(nameof(FullName))]
public string LastName
{
get => _lastName;
private set
{
if (_lastName == value) return;

_lastName = value;
OnPropertyChanged();
}
}

[Bind]
public string FullName => $"{_firstName} {_lastName}";
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<LangVersion>13</LangVersion>
<LangVersion>14</LangVersion>

<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
<PackageId>Aspid.MVVM.Generators</PackageId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspid.Generators.Helper" Version="0.1.0" />
<PackageReference Include="Aspid.Generators.Helper.Unity" Version="0.1.0" />
<PackageReference ExcludeAssets="runtime" Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference ExcludeAssets="runtime" Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0"/>
<PackageReference ExcludeAssets="runtime" Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.0"/>
<PackageReference Include="SourceGenerator.Foundations" Version="2.0.13" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@
using System.Threading;
using System.Diagnostics;
using Microsoft.CodeAnalysis;
using Aspid.Generator.Helpers;
using Aspid.Generators.Helper;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp;
using System.Runtime.CompilerServices;
using Aspid.MVVM.Generators.Binders.Data;
using Aspid.MVVM.Generators.Descriptions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Aspid.MVVM.Generators.Generators.Binders.Data;
using Classes = Aspid.MVVM.Generators.Generators.Descriptions.Classes;

namespace Aspid.MVVM.Generators.Binders;
namespace Aspid.MVVM.Generators.Generators.Binders;

public partial class BinderGenerator
{
private static FoundForGenerator<BinderData> FindBinders(GeneratorSyntaxContext context,
private static BinderData? FindBinders(GeneratorSyntaxContext context,
CancellationToken cancellationToken)
{
Debug.Assert(context.Node is TypeDeclarationSyntax);
var candidate = Unsafe.As<TypeDeclarationSyntax>(context.Node);
var symbol = context.SemanticModel.GetDeclaredSymbol(candidate, cancellationToken);

if (symbol is null) return default;
if (!symbol.HasInterfaceInSelfOrBases(Classes.IBinder, out var binderInterface)) return default;
if (symbol is null) return null;
if (!symbol.TryGetAnyInterfaceInSelfAndBases(out var binderInterface, Classes.IBinder)) return null;

var hasBinderLogInBaseType = false;
const string setValueName = "SetValue";
Expand All @@ -35,16 +35,22 @@ private static FoundForGenerator<BinderData> FindBinders(GeneratorSyntaxContext
.Any(binderMethod =>
{
if (binderMethod.Name is not setValueName) return false;

return binderMethod.EqualsSignature(method) &&
method.ExplicitInterfaceImplementations.Length != 0;
});

if (methodsExplicitImplemented) return default;

if (!hasBinderLogInBaseType
if (methodsExplicitImplemented) return null;

// Check if IAnyBinder.SetValue<T> is already explicitly implemented
if (method.IsGenericMethod && method.Name == setValueName
&& method.ExplicitInterfaceImplementations.Any(m =>
m.ContainingType.Name is "IAnyBinder"))
return null;

if (!hasBinderLogInBaseType
&& !SymbolEqualityComparer.Default.Equals(type, symbol)
&& method.HasAnyAttribute(Classes.BinderLogAttribute))
&& method.HasAnyAttributeInSelf(Classes.BinderLogAttribute))
{
hasBinderLogInBaseType = true;
}
Expand All @@ -55,17 +61,25 @@ private static FoundForGenerator<BinderData> FindBinders(GeneratorSyntaxContext

foreach (var method in symbol.GetMembers().OfType<IMethodSymbol>())
{
if (method.Parameters.Length != 1) continue;
if (method.Parameters.Length is not 1) continue;
if (method.NameFromExplicitImplementation() != setValueName) continue;
if (!symbol.HasInterfaceInSelfOrBases($"{Classes.IBinder.FullName}<{method.Parameters[0].Type.ToDisplayString()}>")) continue;

if (method.HasAnyAttribute(Classes.BinderLogAttribute) &&

var isIBinderMethod = !method.IsGenericMethod
&& symbol.HasAnyInterfaceInSelfAndBases(
$"{Classes.IBinder.FullName}<{method.Parameters[0].Type.ToDisplayString()}>");

var isIAnyBinderMethod = method is { IsGenericMethod: true, TypeParameters.Length: 1 }
&& symbol.HasAnyInterfaceInSelfAndBases(Classes.IAnyBinder.FullName);

if (!isIBinderMethod && !isIAnyBinderMethod) continue;

if (method.HasAnyAttributeInSelf(Classes.BinderLogAttribute) &&
!method.ExplicitInterfaceImplementations.Any())
binderLogMethods.Add(method);
}
if (binderLogMethods.Count == 0) return default;

return new FoundForGenerator<BinderData>(new BinderData(symbol, candidate, hasBinderLogInBaseType, binderLogMethods));

return binderLogMethods.Count is 0
? null
: new BinderData(symbol, candidate, hasBinderLogInBaseType, binderLogMethods);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Microsoft.CodeAnalysis;
using Aspid.Generator.Helpers;
using Aspid.MVVM.Generators.Binders.Body;
using Aspid.MVVM.Generators.Binders.Data;
using Aspid.MVVM.Generators.Descriptions;
using Aspid.Generators.Helper;
using Aspid.MVVM.Generators.Generators.Binders.Body;
using Aspid.MVVM.Generators.Generators.Binders.Data;
using Aspid.MVVM.Generators.Generators.Descriptions;

namespace Aspid.MVVM.Generators.Binders;
namespace Aspid.MVVM.Generators.Generators.Binders;

public partial class BinderGenerator
{
Expand All @@ -14,7 +14,7 @@ private static void GenerateCode(SourceProductionContext context, BinderData bin
{
var declaration = binderData.Declaration;
var @namespace = declaration.GetNamespaceName();
var declarationText = declaration.GetDeclarationText();
var declarationText = new DeclarationText(declaration);

GenerateBinderLog(@namespace, new BinderDataSpan(binderData), context, declarationText);
}
Expand All @@ -31,15 +31,15 @@ private static void GenerateBinderLog(

#if DEBUG
code.AppendLine($"#if !{Defines.ASPID_MVVM_BINDER_LOG_DISABLED}")
.AppendClassBegin(@namespace, declarationText)
.BeginClass(@namespace, declarationText)
.AppendBinderLogBody(data)
.AppendClassEnd(@namespace)
.EndClass(@namespace)
.AppendLine("#endif");
#else
code.AppendLine($"#if {Defines.UNITY_EDITOR} && !{Defines.ASPID_MVVM_BINDER_LOG_DISABLED}")
.AppendClassBegin(@namespace, declarationText)
code.AppendLine($"#if {Aspid.Generators.Helper.Unity.Defines.UNITY_EDITOR} && !{Defines.ASPID_MVVM_BINDER_LOG_DISABLED}")
.BeginClass(@namespace, declarationText)
.AppendBinderLogBody(data)
.AppendClassEnd(@namespace)
.EndClass(@namespace)
.Append("#endif");
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Aspid.MVVM.Generators.Binders;
namespace Aspid.MVVM.Generators.Generators.Binders;

[Generator]
public partial class BinderGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
// ReSharper disable once NullableWarningSuppressionIsUsed
var provider = context.SyntaxProvider.CreateSyntaxProvider(SyntacticPredicate, FindBinders)
.Where(foundForSourceGenerator => foundForSourceGenerator.IsNeed)
.Select((foundForSourceGenerator, _) => foundForSourceGenerator.Container);
.Where(data => data.HasValue)
.Select((data, _) => data!.Value);

context.RegisterSourceOutput(
source: provider,
Expand Down
Loading