Skip to content

Commit

Permalink
Merge pull request #80 from Nyrest/PublicFastNewOption
Browse files Browse the repository at this point in the history
Add FastNew_PublicFastNew option
  • Loading branch information
Nyrest authored Aug 15, 2024
2 parents 9648cbb + cd3f9da commit 43c0ea0
Show file tree
Hide file tree
Showing 32 changed files with 244 additions and 81 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
5.0.x
6.0.x
7.0.x
8.0.x
9.0.x
include-prerelease: true
- name: Restore dependencies
run: dotnet restore
Expand Down
4 changes: 3 additions & 1 deletion FastGenericNew.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Root", "Root", "{F142034C-8
Benchmark_ReferenceType.png = Benchmark_ReferenceType.png
Benchmark_ValueType.png = Benchmark_ValueType.png
FastGenericNew.Shared.props = FastGenericNew.Shared.props
.github\workflows\publish.yml = .github\workflows\publish.yml
README.md = README.md
.github\workflows\tests.yml = .github\workflows\tests.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGenericNew.Tests", "src\FastGenericNew.Tests\FastGenericNew.Tests.csproj", "{7A750C15-4CF3-4F5B-BFA8-AFBB98827770}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGenericNew.Benchmarks", "src\FastGenericNew.Benchmarks\FastGenericNew.Benchmarks.csproj", "{24108B29-8FAD-4080-90B4-0A6A19CE06BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FastGenericNew.SourceGenerator.InternalGenerator", "src\FastGenericNew.SourceGenerator.InternalGenerator\FastGenericNew.SourceGenerator.InternalGenerator.csproj", "{33032C07-28EF-4AD6-BE00-32303BB9DA7B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FastGenericNew.SourceGenerator.InternalGenerator", "src\FastGenericNew.SourceGenerator.InternalGenerator\FastGenericNew.SourceGenerator.InternalGenerator.csproj", "{33032C07-28EF-4AD6-BE00-32303BB9DA7B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net461;net48</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net462;net481</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>10</LangVersion>
Expand All @@ -25,6 +25,7 @@

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 2 additions & 3 deletions src/FastGenericNew.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@

ManualConfig config = ManualConfig.Create(DefaultConfig.Instance);
config.AddJob(
Job.Default.WithRuntime(ClrRuntime.Net461),
Job.Default.WithRuntime(ClrRuntime.Net48),
Job.Default.WithRuntime(CoreRuntime.Core31),
Job.Default.WithRuntime(ClrRuntime.Net462),
Job.Default.WithRuntime(ClrRuntime.Net481),
Job.Default.WithRuntime(CoreRuntime.Core60),
Job.Default.WithRuntime(CoreRuntime.Core80),
Job.Default.WithRuntime(CoreRuntime.Core90)
Expand Down
6 changes: 3 additions & 3 deletions src/FastGenericNew.Shared.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Version>3.2.0-preview1</Version>
<AssemblyVersion>3.2.0</AssemblyVersion>
<Version>3.3.0</Version>
<AssemblyVersion>3.3.0</AssemblyVersion>
</PropertyGroup>

<!-- Ensure the asset files are referenced in the project file -->
Expand Down Expand Up @@ -32,7 +32,7 @@ C# 10 Parameterless struct constructors Support (Both invokes or not)
<RepositoryUrl>https://github.com/Nyrest/FastGenericNew</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageProjectUrl>https://github.com/Nyrest/FastGenericNew</PackageProjectUrl>
<PackageTags>Performance, Fast, Generic, New, Expression, Optimization, CreateInstance, Activator, $(PackageTagsPostfix)</PackageTags>
<PackageTags>Performance, Fast, Generic, New, Expression, Optimization, CreateInstance, Activator, DynamicMethod, $(PackageTagsPostfix)</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>Logo.png</PackageIcon>
<IsPackable>true</IsPackable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ public override CodeGenerationResult Generate(in GeneratorOptions options)
builder.WriteFileHeader();
builder.StartNamespace();
builder.Indent(1);
builder.AppendKeyword("public static partial class");
builder.AppendKeyword("static partial class");
builder.Append(ClassName);
builder.StartBlock(1);

builder.AppendLine($@"
/// <summary>
/// <para>Create an instance of <typeparamref name=""T"" /></para>
/// <para>Returns <c><see langword=""new"" /> <typeparamref name=""T"" />()</c> if <typeparamref name=""T""/> is a <see cref=""ValueType""/>(struct)</para>
/// <para>This <b>CAN</b> call the Parameterless Constructor of the <see cref=""ValueType""/>(struct)</para>
/// <para>This <b>CAN</b> call the Parameterless Constructor for <see cref=""ValueType""/>(struct)</para>
/// </summary>
/// <typeparam name=""T"">The type to create.</typeparam>
/// <returns>A new instance of <typeparamref name=""T"" /></returns>
Expand All @@ -39,7 +38,7 @@ public static T CreateInstance<
return {options.GlobalNSDot()}{FastNewCoreGenerator.ClassName}<T>.{FastNewCoreGenerator.CompiledDelegateName}();
#else
return typeof(T).IsValueType
? System.Activator.CreateInstance<T>() // This will be optimized by JIT
? System.Activator.CreateInstance<T>() // Value Types will be optimized by JIT in CoreCLR
#if {ClrAllocatorGenerator.ppEnabled}
: ({options.GlobalNSDot()}{ClrAllocatorGenerator.ClassName}<T>.IsSupported
Expand All @@ -54,7 +53,7 @@ public static T CreateInstance<
/// <summary>
/// Create an instance of <typeparamref name=""T"" /> <br/>
/// Returns <c><see langword=""default"" />(<typeparamref name=""T"" />)</c> if <typeparamref name=""T""/> is a <see cref=""ValueType""/>(struct) <br/>
/// This <b>WILL NOT</b> call the Parameterless Constructor of the <see cref=""ValueType""/>(struct)
/// This <b>WILL NOT</b> call the Parameterless Constructor for <see cref=""ValueType""/>(struct)
/// </summary>
/// <typeparam name=""T"">The type to create.</typeparam>
/// <returns>A new instance of <typeparamref name=""T"" /></returns>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public override CodeGenerationResult Generate(in GeneratorOptions options)
builder.WriteFileHeader();
builder.StartNamespace();
builder.Indent(1);
builder.AppendKeyword("public static partial class");
builder.AppendKeyword("static partial class");
builder.Append(ClassName);

builder.StartBlock(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace FastGenericNew.SourceGenerator.CodeGenerators;

public class FastNewVisibilityGenerator : CodeGenerator<FastNewVisibilityGenerator>
{
public override string Filename => "FastNewVisibility.g.cs";

internal const string ClassName = "FastNew";

public override CodeGenerationResult Generate(in GeneratorOptions options)
{
CodeBuilder builder = new(1024, in options);
builder.WriteFileHeader();
builder.StartNamespace();
builder.Indent(1);

builder.AppendKeyword(options.PublicFastNew ? "public" : "internal");

builder.AppendKeyword("static partial class");
builder.Append(ClassName);
builder.StartBlock(1);
builder.EndBlock(1);
builder.EndNamespace();

return builder.BuildAndDispose(this);
}

public override bool ShouldUpdate(in GeneratorOptions oldValue, in GeneratorOptions newValue) =>
base.ShouldUpdate(oldValue, newValue)
|| oldValue.PublicFastNew != newValue.PublicFastNew;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public override CodeGenerationResult Generate(in GeneratorOptions options)
builder.WriteFileHeader();
builder.StartNamespace();
builder.Indent(1);
builder.AppendKeyword("public static partial class");
builder.AppendKeyword("static partial class");
builder.Append(ClassName);

builder.StartBlock(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class ThrowHelperGenerator : CodeGenerator<ThrowHelperGenerator>
{
public override string Filename => "ThrowHelper.g.cs";

internal const string ClassName = "ThrowHelper";
internal const string ClassName = "FastNewThrowHelper";

internal const string SmartThrowName = "SmartThrowImpl";

Expand All @@ -15,15 +15,15 @@ public override CodeGenerationResult Generate(in GeneratorOptions options)
builder.StartNamespace();
builder.AppendLine(@$"
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)]
internal static partial class ThrowHelper
internal static partial class {ClassName}
{{
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining | global::System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]
#if NET5_0_OR_GREATER
[global::System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute(""SmartThrowImpl``1()"", typeof({options.GlobalNSDot()}{ClassName}))]
#endif
");
builder.AppendLine(@$"
public static global::System.Reflection.MethodInfo GetSmartThrow<T>() => typeof({options.GlobalNSDot()}ThrowHelper).GetMethod(""SmartThrowImpl"", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)!.MakeGenericMethod(typeof(T));
public static global::System.Reflection.MethodInfo GetSmartThrow<T>() => typeof({options.GlobalNSDot()}{ClassName}).GetMethod(""SmartThrowImpl"", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)!.MakeGenericMethod(typeof(T));
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.NoInlining | global::System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]
public static T SmartThrowImpl<T>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public override CodeGenerationResult Generate(in GeneratorOptions options)
builder.WriteFileHeader();
builder.StartNamespace();

builder.AppendKeyword("public static partial class");
builder.AppendKeyword("static partial class");
builder.Append(ClassName);

builder.StartBlock(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<!-- Library Properties -->
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>preview</LangVersion>
<LangVersion>11.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsRoslynComponent>true</IsRoslynComponent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
<CompilerVisibleProperty Include="FastNew_MultiThreadedGeneration" />
<CompilerVisibleProperty Include="FastNew_OutputGenerationInfo" />
<CompilerVisibleProperty Include="FastNew_AllowUnsafeImplementation" />
<CompilerVisibleProperty Include="FastNew_PublicFastNew" />
</ItemGroup>
</Project>
5 changes: 4 additions & 1 deletion src/FastGenericNew.SourceGenerator/GeneratorOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public readonly partial record struct GeneratorOptions
[GeneratorOption(true)]
public bool AlertGeneratedFile { get; }

[GeneratorOption(false)]
[GeneratorOption(true)]
public bool DisableGeneratorCache { get; }

[GeneratorOption(false)]
Expand All @@ -44,6 +44,9 @@ public readonly partial record struct GeneratorOptions
[GeneratorOption(false, PresentPreProcessor = true)]
public bool AllowUnsafeImplementation { get; }

[GeneratorOption(false)]
public bool PublicFastNew { get; }

// ctor will be generated by InternalGenerator
//public GeneratorOptions(AnalyzerConfigOptionsProvider? provider)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ public GeneratorOptions(AnalyzerConfigOptionsProvider? provider)
Namespace = options.GetOrDefault(nameof(Namespace), "FastGenericNew");
ForceFastNewDelegate = options.GetOrDefault(nameof(ForceFastNewDelegate), false);
AlertGeneratedFile = options.GetOrDefault(nameof(AlertGeneratedFile), true);
DisableGeneratorCache = options.GetOrDefault(nameof(DisableGeneratorCache), false);
DisableGeneratorCache = options.GetOrDefault(nameof(DisableGeneratorCache), true);
PrettyOutput = options.GetOrDefault(nameof(PrettyOutput), false);
MultiThreadedGeneration = options.GetOrDefault(nameof(MultiThreadedGeneration), true);
OutputGenerationInfo = options.GetOrDefault(nameof(OutputGenerationInfo), false);
AllowUnsafeImplementation = options.GetOrDefault(nameof(AllowUnsafeImplementation), false);
PublicFastNew = options.GetOrDefault(nameof(PublicFastNew), false);
}
}
4 changes: 2 additions & 2 deletions src/FastGenericNew.Tests/FastGenericNew.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net48</TargetFrameworks>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
Expand Down
8 changes: 8 additions & 0 deletions src/FastGenericNew.Tests/TestData.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

Expand Down Expand Up @@ -35,6 +38,11 @@ public static class TestData
typeof(nint),
typeof(nuint),

#if NET8_0_OR_GREATER
typeof(Int128),
typeof(UInt128),
#endif

#endregion

typeof(DateTime),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ public class ExceptionsTest
[Test()]
public void ExceptionInterface()
{
if (!ClrAllocator<IEnumerable>.IsSupported) Assert.Ignore("Unsupported");
try
{
ClrAllocator<IEnumerable>.CreateInstance();
Assert.Fail("The expected exception is not thrown.");
}
catch (MissingMethodException e)
catch (Exception e)
{
Assert.IsTrue(e.Message.StartsWith("Cannot create an instance of an interface"));
}
Expand All @@ -20,6 +21,7 @@ public void ExceptionInterface()
[Test()]
public void ExceptionAbstract()
{
if (!ClrAllocator<Stream>.IsSupported) Assert.Ignore("Unsupported");
try
{
ClrAllocator<Stream>.CreateInstance();
Expand All @@ -34,6 +36,7 @@ public void ExceptionAbstract()
[Test()]
public void ExceptionPLString()
{
if (!ClrAllocator<string>.IsSupported) Assert.Ignore("Unsupported");
try
{
ClrAllocator<string>.CreateInstance();
Expand All @@ -49,6 +52,7 @@ public void ExceptionPLString()
[Test()]
public void ExceptionNotFoundNoParameter()
{
if (!ClrAllocator<DemoClassNoParamlessCtor>.IsSupported) Assert.Ignore("Unsupported");
try
{
ClrAllocator<DemoClassNoParamlessCtor>.CreateInstance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class ReferenceTypes
[Test]
public void Object()
{
if (!ClrAllocator<object>.IsSupported) Assert.Ignore("Unsupported");
var expected = Activator.CreateInstance<object>();
var actual = ClrAllocator<object>.CreateInstance();
Assert.IsTrue(expected.GetType() == actual.GetType());
Expand All @@ -17,6 +18,7 @@ public void Object()
[Parallelizable(ParallelScope.All)]
public void CommonTypes<T>()
{
if (!ClrAllocator<T>.IsSupported) Assert.Ignore("Unsupported");
var expected = Activator.CreateInstance<T>();
var actual = ClrAllocator<T>.CreateInstance();
Assert.AreEqual(expected, actual);
Expand All @@ -26,6 +28,7 @@ public void CommonTypes<T>()
[Parallelizable(ParallelScope.All)]
public void ParallelNew<T>()
{
if (!ClrAllocator<T>.IsSupported) Assert.Ignore("Unsupported");
const int count = 512;
T[] array = new T[count];
Parallel.For(0, count, new ParallelOptions() { MaxDegreeOfParallelism = count }, i =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class ValueTypes
[Parallelizable(ParallelScope.All)]
public void CommonTypes<T>()
{
if (!ClrAllocator<T>.IsSupported) Assert.Ignore("Unsupported");
var expected = Activator.CreateInstance<T>();
var actual = FastNew<T>.CompiledDelegate();
Assert.AreEqual(expected, actual);
Expand Down
Loading

0 comments on commit 43c0ea0

Please sign in to comment.