Skip to content

Commit

Permalink
- CHANGELOG
Browse files Browse the repository at this point in the history
- [NoDomainReloadSupport] added to exclude classes
- Namespace black list added
  • Loading branch information
LurkingNinjaDev committed Nov 6, 2023
1 parent 0d88d8c commit 528c4c3
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 27 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog
All notable changes to this project will be documented in this file.

[READ ME](./README.md) | [MIT LICENSE](./LICENSE)
## [0.0.2] - 2022-11-06
### Added
- This CHANGELOG
- [NoDomainReloadSupport] added to exclude classes
- Namespace black list added

## [0.0.1] - 2023-11-05
### Added
- Initial release with existing code.
57 changes: 49 additions & 8 deletions Common.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
using System.Linq;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;

namespace LurkingNinja.DomainReloadSG
{
internal static class Common
{
private const string FILENAME_POSTFIX = "_codegen.cs";

internal const string NO_DOMAIN_SUPPORT_ATTRIBUTE = "NoDomainReloadSupport";

/*
* {0} name space if exists
* {1} closing bracket for namespace if needed
Expand All @@ -19,6 +26,30 @@ internal static class Common
{2}
{1}";

internal const string ATTRIBUTES_SOURCE = @"using System;
namespace LurkingNinja.Attributes
{
[AttributeUsage(AttributeTargets.Class)]
internal class " + NO_DOMAIN_SUPPORT_ATTRIBUTE + @" : Attribute
{
public " + NO_DOMAIN_SUPPORT_ATTRIBUTE + @"() {}
}
}";

/**
* {0} Class name
* {1} Generated assignments
*/
internal const string SOURCE_TEMPLATE = @"public partial class {0}
{{
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void ApplyStaticFieldsAndEventHandlers()
{{
{1}
}}
}}";

internal static string NamespaceTemplateResolve(string nameSpace, string source)
{
var ns = GetNamespaceTemplate(nameSpace);
Expand Down Expand Up @@ -46,13 +77,19 @@ internal static string NamespaceTemplateResolve(string nameSpace, string source)
internal static bool IsVoidFunction(MethodDeclarationSyntax ms) =>
ms.ReturnType is PredefinedTypeSyntax predefined && predefined.Keyword.IsKind(SyntaxKind.VoidKeyword);

internal static void AddSource(GeneratorExecutionContext context,
string fileName, string source)
{
fileName = $"{fileName}_codegen.cs";
context.AddSource(fileName, source);
}

internal static bool HasAttribute(ClassDeclarationSyntax cds, string attributeName) =>
cds.AttributeLists
.Any(cdsAttributeList => cdsAttributeList.Attributes
.Any(cdsAttribute => cdsAttribute.ToString().Trim().ToLower()
.Equals(attributeName.Trim().ToLower())));

internal static void AddSource(GeneratorExecutionContext context, string fileName, string source) =>
context.AddSource($"{fileName}{FILENAME_POSTFIX}", source);

internal static void AddSource(GeneratorInitializationContext context, string fileName, string source) =>
context.RegisterForPostInitialization(ctx =>
ctx.AddSource($"{fileName}{FILENAME_POSTFIX}", SourceText.From(source, Encoding.UTF8)));

internal static string GetNamespace(SyntaxNode node)
{
var nameSpace = string.Empty;
Expand Down Expand Up @@ -90,5 +127,9 @@ private static (string, string) GetNamespaceTemplate(string potentialNamespace)
? string.Empty
: "}");
}

internal static void Log(string message) =>
File.AppendAllText(@"D:\log.txt", $"{message}\n", Encoding.UTF8);

}
}
6 changes: 6 additions & 0 deletions DomainReloadSG.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>LurkingNinja.DomainReloadSG</RootNamespace>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
<AssemblyVersion>0.2</AssemblyVersion>
<FileVersion>0.2</FileVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.1.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.1.0" />
</ItemGroup>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy &quot;D:\DomainReloadSG\bin\Release\netstandard2.0\DomainReloadSG.dll&quot; &quot;D:\DomainReload\Assets\DomainReloadSG.dll&quot;" />
</Target>

</Project>
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# DomainReloadSG
# Domain Reload support through Source Generator
Source Generator to support Domain Reload off in Unity (handle static fields and event handlers).

[MIT LICENSE](./LICENSE) | [CHANGELOG](./CHANGELOG.md)
## Usage
You have two ways to use this repository:
### 1 - Use a release
Expand All @@ -23,9 +24,12 @@ You have two ways to use this repository:
### Limitations
- The class you're augmenting _has to be_ decorated with the ```partial``` keyword.
- Currently there is no way of excluding classes, static fields or event handlers from this service.
- Currently there is no way of excluding static fields or methods from this service.
- If you're using extra namespaces currently you need to explicitly write it in the code as opposed of in a ```using``` statement.

### Exclusion
- Decorate your partial class with ```[NoDomainReloadSupport]``` attribute if you want to exclude it completely.

### Example
```csharp
using UnityEngine;
Expand Down
29 changes: 12 additions & 17 deletions SourceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,11 @@ namespace LurkingNinja.DomainReloadSG
[Generator]
public class SourceGenerator : ISourceGenerator
{
/**
* {0} Class name
* {1} Generated assignments
*/
private const string SOURCE_TEMPLATE = @"public partial class {0}
{{
[UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.SubsystemRegistration)]
static void ApplyStaticFieldsAndEventHandlers()
{{
{1}
}}
}}";

public void Initialize(GeneratorInitializationContext context) =>
public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new DrSyntaxReceiver());
Common.AddSource(context, "DomainReloadSG_Attributes", Common.ATTRIBUTES_SOURCE);
}

public void Execute(GeneratorExecutionContext context)
{
Expand All @@ -51,29 +41,34 @@ public void Execute(GeneratorExecutionContext context)

foreach (var handler in dsr.eventHandlers) lines.AppendLine($"\t\t\t{handler}");

var source = string.Format(SOURCE_TEMPLATE,
var source = string.Format(Common.SOURCE_TEMPLATE,
/*{0}*/dsr.ClassToAugment.Identifier.ToFullString(),
/*{1}*/lines);

Common.AddSource(context, dsr.ClassToAugment.Identifier.ToFullString(),
Common.AddSource(context, dsr.ClassToAugment.Identifier.ToFullString().Trim(),
Common.NamespaceTemplateResolve(nameSpace, source));
}
}

internal class DrSyntaxReceiver : ISyntaxReceiver
{
// Something[.maybeSomething] += MethodNameFromCurrentClass;
private const string EVENT_SUBSCRIPTION_REGEX = @"^\w+[.\w]*\s*\+\=\s*{0}\s*;$";

internal ClassDeclarationSyntax ClassToAugment { get; private set; }
internal readonly List<FieldDeclarationSyntax> fields = new List<FieldDeclarationSyntax>();
internal readonly List<string> eventHandlers = new List<string>();

private readonly string[] _nameSpaceBlackList = { "TMPro" };

public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if (!(syntaxNode is ClassDeclarationSyntax cds)) return;
if (Common.IsAbstractClass(cds)) return;
if (!Common.IsPartial(cds)) return;

if (Common.HasAttribute(cds, Common.NO_DOMAIN_SUPPORT_ATTRIBUTE)) return;
if (_nameSpaceBlackList.Contains(Common.GetNamespace(cds))) return;

var potentialMethods = new List<string>();

fields.Clear();
Expand Down

0 comments on commit 528c4c3

Please sign in to comment.