Skip to content

Commit

Permalink
Merge branch 'master' into feature/ecs-unmanaged-system
Browse files Browse the repository at this point in the history
  • Loading branch information
stenyin committed Mar 14, 2023
2 parents 8f434a1 + 99c6e8c commit 26e588e
Show file tree
Hide file tree
Showing 61 changed files with 8,449 additions and 2,605 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/notify.yaml
Expand Up @@ -8,9 +8,10 @@ jobs:
star:
runs-on: ubuntu-latest
steps:
- uses: 8398a7/action-slack@v1
- uses: 8398a7/action-slack@v3
with:
payload: |
{ "text": "☆${{ github.event.repository.stargazers_count }} ${{ github.event.repository.html_url }}" }
status: ${{ job.status }}
fields: repo
text: "☆ from https://github.com/${{ github.event.sender.login }}, Total: ${{ github.event.repository.stargazers_count }}"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
7 changes: 4 additions & 3 deletions .github/workflows/test.yaml
Expand Up @@ -11,9 +11,9 @@ jobs:
NUGET_XMLDOC_MODE: skip
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 3.1.101
dotnet-version: 6.0.x
- run: dotnet test -c Debug ./VContainer.StandaloneTests

test-unity:
Expand All @@ -26,7 +26,8 @@ jobs:
- 2019.4.25f1
- 2019.3.15f1
# feature: ['None', 'UniTask', 'ECS']
feature: ['Default', 'UniTask', 'CodeGen']
# feature: ['Default', 'UniTask', 'CodeGen']
feature: ['Default', 'UniTask']
include:
- unityVersion: 2021.1.4f1
license: UNITY_LICENSE_2021_1
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -399,3 +399,6 @@ VContainer.Benchmark/obj/*
# Rider
**/.idea/*
**/.idea.meta

.DS_Store

13 changes: 4 additions & 9 deletions README.md
Expand Up @@ -21,7 +21,7 @@ The extra fast DI (Dependency Injection) library running on Unity Game Engine.
- Dispatch own PlayerLoopSystem
- Flexible scoping
- Application can freely create nested Lifetime Scope with any async way for you like.
- Pre IL Code generation optimization mode
- Accelerated mode with SourceGenerator (Optional)
- Diagnositcs window on unity editor
- UniTask Integration
- ECS Integration *beta*
Expand Down Expand Up @@ -52,7 +52,7 @@ Visit [vcontainer.hadashikick.jp](https://vcontainer.hadashikick.jp) to view the
1. Navigate to your project's Packages folder and open the manifest.json file.
2. Add this line below the "dependencies": { line
- ```json title="Packages/manifest.json"
"jp.hadashikick.vcontainer": "https://github.com/hadashiA/VContainer.git?path=VContainer/Assets/VContainer#1.12.0",
"jp.hadashikick.vcontainer": "https://github.com/hadashiA/VContainer.git?path=VContainer/Assets/VContainer#1.13.1",
```
3. UPM should now install the package.

Expand All @@ -67,13 +67,8 @@ Visit [vcontainer.hadashikick.jp](https://vcontainer.hadashikick.jp) to view the

### Install manually (using .unitypackage)

1. Navigate to your project's Packages folder and open the manifest.json file.
2. Add this line below the "dependencies": { line
- ```json title="Packages/manifest.json"
"com.unity.nuget.mono-cecil": "1.10.1",
```
3. Download the .unitypackage from [releases](https://github.com/hadashiA/VContainer/releases) page.
4. Open VContainer.x.x.x.unitypackage
1. Download the .unitypackage from [releases](https://github.com/hadashiA/VContainer/releases) page.
2. Open VContainer.x.x.x.unitypackage

## Basic Usage

Expand Down
90 changes: 90 additions & 0 deletions VContainer.SourceGenerator/CodeWriter.cs
@@ -0,0 +1,90 @@
using System;
using System.Text;

namespace VContainer.SourceGenerator
{
public class CodeWriter
{
readonly struct IndentScope : IDisposable
{
readonly CodeWriter source;

public IndentScope(CodeWriter source)
{
this.source = source;
source.IncreasaeIndent();
}

public void Dispose()
{
source.DecreaseIndent();
}
}

readonly struct BlockScope : IDisposable
{
readonly CodeWriter source;

public BlockScope(CodeWriter source, string? startLine = null)
{
this.source = source;
source.AppendLine(startLine);
source.BeginBlock();
}

public void Dispose()
{
source.EndBlock();
}
}

readonly StringBuilder buffer = new();
int indentLevel;

public void AppendLine(string value = "")
{
if (string.IsNullOrEmpty(value))
{
buffer.AppendLine();
}
else
{
buffer.AppendLine($"{new string(' ', indentLevel * 4)} {value}");
}
}

public override string ToString() => buffer.ToString();

public IDisposable BeginIndentScope() => new IndentScope(this);
public IDisposable BeginBlockScope(string? startLine = null) => new BlockScope(this, startLine);

public void IncreasaeIndent()
{
indentLevel++;
}

public void DecreaseIndent()
{
if (indentLevel > 0)
indentLevel--;
}

public void BeginBlock()
{
AppendLine("{");
IncreasaeIndent();
}

public void EndBlock()
{
DecreaseIndent();
AppendLine("}");
}

public void Clear()
{
buffer.Clear();
indentLevel = 0;
}
}
}
89 changes: 89 additions & 0 deletions VContainer.SourceGenerator/DiagnosticDescriptors.cs
@@ -0,0 +1,89 @@
using Microsoft.CodeAnalysis;

namespace VContainer.SourceGenerator
{
static class DiagnosticDescriptors
{
const string Category = "VContainer.SourceGenerator";

public static readonly DiagnosticDescriptor UnexpectedErrorDescriptor = new(
id: "VCON0001",
title: "Unexpected error during generation",
messageFormat: "Unexpected error occurred during code generation: {0}",
category: "Usage",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor AbstractNotAllow = new(
id: "VCON0002",
title: "Injectable type must not be abstract/interface",
messageFormat: "The injectable type of '{0}' is abstract/interface. It is not allowed",
category: Category,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor MultipleCtorAttributeNotSupported = new(
id: "VCON0003",
title: "[Inject] exists in multiple constructors",
messageFormat: "Multiple [Inject] constructors exists in '{0}'",
category: Category,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor MultipleInjectMethodNotSupported = new(
id: "VCON0004",
title: "[Inject] exists in multiple methods",
messageFormat: "Multiple [Inject] methods exists in '{0}'",
category: Category,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor NestedNotSupported = new(
id: "VCON0005",
title: "Nested type is not support to code generation.",
messageFormat: "The injectable object '{0}' is a nested type. It cannot support code generation ",
category: Category,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor PrivateConstructorNotSupported = new(
id: "VCON0006",
title: "The private constructor is not supported to code generation.",
messageFormat: "The injectable constructor of '{0}' is private. It cannot support source generator.",
category: Category,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor PrivateFieldNotSupported = new(
id: "VCON0007",
title: "The private [Inject] field is not supported to code generation.",
messageFormat: "The [Inject] field '{0}' does not have accessible to set from the same dll. It cannot support to inject by the source generator.",
category: Category,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor PrivatePropertyNotSupported = new(
id: "VCON0008",
title: "The private [Inject] property is not supported to code generation",
messageFormat: "The [Inject] '{0}' does not have accessible to set from the same dll. It cannot support to inject by the source generator.",
category: Category,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor PrivateMethodNotSupported = new(
id: "VCON0009",
title: "The private [Inject] method is not supported to code generation.",
messageFormat: "The [Inject] '{0}' does not have accessible to call from the same dll. It cannot support inject by the source generator.",
category: Category,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static readonly DiagnosticDescriptor GenericsNotSupported = new(
id: "VCON0010",
title: "The [Inject] constructor or method that require generics argument is not supported to code generation.",
messageFormat: "[Inject] '{0}' needs generic arguments. It cannot inject by the source generator.",
category: Category,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);
}
}
24 changes: 24 additions & 0 deletions VContainer.SourceGenerator/ReferenceSymbols.cs
@@ -0,0 +1,24 @@
using Microsoft.CodeAnalysis;

namespace VContainer.SourceGenerator
{
public class ReferenceSymbols
{
public static ReferenceSymbols? Create(Compilation compilation)
{
var injectAttribute = compilation.GetTypeByMetadataName("VContainer.InjectAttribute");
if (injectAttribute is null)
return null;
return new ReferenceSymbols
{
VContainerInjectAttribute = injectAttribute,
VContainerInjectIgnoreAttribute = compilation.GetTypeByMetadataName("VContainer.InjectIgnoreAttribute")!,
UnityEngineComponent = compilation.GetTypeByMetadataName("UnityEngine.Component"),
};
}

public INamedTypeSymbol VContainerInjectAttribute { get; private set; }
public INamedTypeSymbol VContainerInjectIgnoreAttribute { get; private set; }
public INamedTypeSymbol? UnityEngineComponent { get; private set; }
}
}
102 changes: 102 additions & 0 deletions VContainer.SourceGenerator/SymbolExtensions.cs
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;

namespace VContainer.SourceGenerator
{
public static class SymbolExtensions
{
public static IEnumerable<ISymbol> GetAllMembers(this INamedTypeSymbol symbol, bool withoutOverride = true)
{
// Iterate Parent -> Derived
if (symbol.BaseType != null)
{
foreach (var item in GetAllMembers(symbol.BaseType))
{
// override item already iterated in parent type
if (!withoutOverride || !item.IsOverride)
{
yield return item;
}
}
}

foreach (var item in symbol.GetMembers())
{
if (!withoutOverride || !item.IsOverride)
{
yield return item;
}
}
}

public static bool ContainsAttribute(this ISymbol symbol, INamedTypeSymbol attribtue)
{
return symbol.GetAttributes().Any(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, attribtue));
}

public static bool CanBeCallFromInternal(this ISymbol symbol)
{
return symbol.DeclaredAccessibility >= Accessibility.Internal;
}

public static string GetClassDeclarationName(this INamedTypeSymbol symbol)
{
if (symbol.TypeArguments.Length == 0)
{
return symbol.Name;
}

var sb = new StringBuilder();

sb.Append(symbol.Name);
sb.Append('<');

var first = true;
foreach (var typeArg in symbol.TypeArguments)
{
if (!first)
{
sb.Append(", ");
}
else
{
first = false;
}
sb.Append(typeArg.Name);
}

sb.Append('>');

return sb.ToString();
}

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) => DistinctBy(source, keySelector, null);

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{
return DistinctByIterator(source, keySelector, comparer);
}

static IEnumerable<TSource> DistinctByIterator<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{
using IEnumerator<TSource> enumerator = source.GetEnumerator();

if (enumerator.MoveNext())
{
var set = new HashSet<TKey>(comparer);
do
{
TSource element = enumerator.Current;
if (set.Add(keySelector(element)))
{
yield return element;
}
}
while (enumerator.MoveNext());
}
}
}
}

0 comments on commit 26e588e

Please sign in to comment.