Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define marker attributes on a external assembly #151

Merged
merged 1 commit into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions src/Jab.Attributes/Jab.Attributes.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>true</IsPackable>
<LangVersion>preview</LangVersion>
<RootNamespace>Jab</RootNamespace>
<DefineConstants>$(DefineConstants);JAB_ATTRIBUTES_PACKAGE;GENERIC_ATTRIBUTES</DefineConstants>
</PropertyGroup>

<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)/../Jab/Attributes.cs" />
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions src/Jab.FunctionalTests.Common/Jab.FunctionalTest.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
<IsTestProject Condition="'$(TargetFramework)' == 'netstandard2.0'">false</IsTestProject>
</PropertyGroup>

<PropertyGroup>
<DefineConstants Condition="'$(FunctionalTestPackageVersion)' == ''">$(DefineConstants);JAB_ATTRIBUTES_REFERENCED</DefineConstants>
</PropertyGroup>

<Target Name="_SetProperties">
<PropertyGroup>
<!-- Force CoreCompile execution -->
Expand All @@ -32,6 +36,7 @@

<ItemGroup Condition="'$(FunctionalTestPackageVersion)' == ''" >
<ProjectReference Include="..\Jab\Jab.csproj" OutputItemType="Analyzer" />
<ProjectReference Include="..\Jab.Attributes\Jab.Attributes.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" />
</ItemGroup>

<Target Name="DefineJabPreview" BeforeTargets="CoreCompile" Condition="'$(FunctionalTestPackageVersion)' == ''">
Expand Down
1 change: 0 additions & 1 deletion src/Jab.Tests/GeneratorAnalyzerTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Testing.Verifiers;
Expand Down
2 changes: 1 addition & 1 deletion src/Jab.Tests/Jab.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<ProjectReference Include="..\Jab\Jab.csproj" />

<Content Include="..\Jab\Attributes.cs" CopyToOutputDirectory="PreserveNewest" />

<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
Expand Down
111 changes: 95 additions & 16 deletions src/Jab/Attributes.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// <auto-generated/>

#if !JAB_ATTRIBUTES_REFERENCED || JAB_ATTRIBUTES_PACKAGE

using System;
using System.Threading.Tasks;

Expand All @@ -8,18 +10,33 @@
namespace Jab
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
internal class ServiceProviderAttribute: Attribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class ServiceProviderAttribute: Attribute
{
public Type[]? RootServices { get; set; }
}

[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
internal class ServiceProviderModuleAttribute: Attribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class ServiceProviderModuleAttribute: Attribute
{
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class ImportAttribute: Attribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class ImportAttribute: Attribute
{
public Type ModuleType { get; }

Expand All @@ -30,7 +47,12 @@ public ImportAttribute(Type moduleType)
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class SingletonAttribute: Attribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class SingletonAttribute: Attribute
{
public Type ServiceType { get; }

Expand All @@ -53,7 +75,12 @@ public SingletonAttribute(Type serviceType, Type implementationType)
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class TransientAttribute : Attribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class TransientAttribute : Attribute
{
public Type ServiceType { get; }

Expand All @@ -74,7 +101,12 @@ public TransientAttribute(Type serviceType, Type implementationType)
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class ScopedAttribute : Attribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class ScopedAttribute : Attribute
{
public Type ServiceType { get; }

Expand All @@ -96,39 +128,64 @@ public ScopedAttribute(Type serviceType, Type implementationType)

#if GENERIC_ATTRIBUTES
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class ImportAttribute<TModule> : ImportAttribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class ImportAttribute<TModule> : ImportAttribute
{
public ImportAttribute() : base(typeof(TModule))
{
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class TransientAttribute<TService> : TransientAttribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class TransientAttribute<TService> : TransientAttribute
{
public TransientAttribute() : base(typeof(TService))
{
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class TransientAttribute<TService, TImpl> : TransientAttribute where TImpl: TService
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class TransientAttribute<TService, TImpl> : TransientAttribute where TImpl: TService
{
public TransientAttribute() : base(typeof(TService), typeof(TImpl))
{
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class ScopedAttribute<TService> : ScopedAttribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class ScopedAttribute<TService> : ScopedAttribute
{
public ScopedAttribute() : base(typeof(TService))
{
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class ScopedAttribute<TService, TImpl> : ScopedAttribute where TImpl: TService
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class ScopedAttribute<TService, TImpl> : ScopedAttribute where TImpl: TService
{
public ScopedAttribute() : base(typeof(TService), typeof(TImpl))
{
Expand All @@ -137,15 +194,25 @@ public ScopedAttribute() : base(typeof(TService), typeof(TImpl))


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class SingletonAttribute<TService> : SingletonAttribute
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class SingletonAttribute<TService> : SingletonAttribute
{
public SingletonAttribute() : base(typeof(TService))
{
}
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = true)]
internal class SingletonAttribute<TService, TImpl> : SingletonAttribute where TImpl: TService
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
class SingletonAttribute<TService, TImpl> : SingletonAttribute where TImpl: TService
{
public SingletonAttribute() : base(typeof(TService), typeof(TImpl))
{
Expand All @@ -154,16 +221,28 @@ public SingletonAttribute() : base(typeof(TService), typeof(TImpl))

#endif

internal interface IServiceProvider<T>
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
interface IServiceProvider<T>
{
T GetService();
}

internal static class JabHelpers
#if JAB_ATTRIBUTES_PACKAGE
public
#else
internal
#endif
static class JabHelpers
{
public static InvalidOperationException CreateServiceNotFoundException<T>()
{
return new InvalidOperationException($"Service Type {typeof(T)} not registered");
}
}
}
}

#endif
24 changes: 19 additions & 5 deletions src/Jab/ServiceProviderBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

internal class KnownTypes
{
public const string JabAttributesAssemblyName = "Jab.Attributes";
public const string TransientAttributeShortName = "Transient";
public const string SingletonAttributeShortName = "Singleton";
public const string ScopedAttributeShortName = "Scoped";
Expand Down Expand Up @@ -123,7 +124,12 @@ internal class ServiceProviderBuilder
public ServiceProviderBuilder(GeneratorContext context)
{
_context = context;
_knownTypes = new KnownTypes(context.Compilation, context.Compilation.Assembly);

var assemblySymbol =
pakrym marked this conversation as resolved.
Show resolved Hide resolved
context.Compilation.SourceModule.ReferencedAssemblySymbols.FirstOrDefault(
s => s.Name == KnownTypes.JabAttributesAssemblyName)
?? context.Compilation.Assembly;
_knownTypes = new KnownTypes(context.Compilation, assemblySymbol);
}

public ServiceProvider[] BuildRoots()
Expand Down Expand Up @@ -862,10 +868,18 @@ private void ProcessModule(ITypeSymbol serviceProviderType, List<ServiceRegistra
// TODO: idempotency
bool isModule = false;
// If module it in another assembly use KnownTypes native to that assembly
var knownTypes =
SymbolEqualityComparer.Default.Equals(moduleType.ContainingAssembly, _context.Compilation.Assembly)
? _knownTypes
: new KnownTypes(_context.Compilation, moduleType.ContainingAssembly);
KnownTypes knownTypes;
if (SymbolEqualityComparer.Default.Equals(moduleType.ContainingAssembly, _context.Compilation.Assembly))
{
knownTypes = _knownTypes;
}
else
{
var assemblySymbol = moduleType.ContainingModule.ReferencedAssemblySymbols.FirstOrDefault(
s => s.Name == KnownTypes.JabAttributesAssemblyName)
?? moduleType.ContainingAssembly;
knownTypes = new KnownTypes(_context.Compilation, assemblySymbol);
}

foreach (var attributeData in moduleType.GetAttributes())
{
Expand Down
8 changes: 8 additions & 0 deletions src/Jab/build/Jab.targets
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project>
<PropertyGroup>
<PrepareForBuildDependsOn>$(PrepareForBuildDependsOn);_JabReferences</PrepareForBuildDependsOn>
<DefineConstants Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND
($([MSBuild]::VersionGreaterThanOrEquals($(_TargetFrameworkVersionWithoutV), '7.0')) OR
($([MSBuild]::VersionGreaterThanOrEquals($(_TargetFrameworkVersionWithoutV), '6.0')) AND '$(LangVersion)'=='preview'))">$(DefineConstants);GENERIC_ATTRIBUTES</DefineConstants>
Expand All @@ -13,4 +14,11 @@
Condition="$([System.String]::Copy('%(Analyzer.Identity)').IndexOf('Jab.dll')) &gt;= 0"/>
</ItemGroup>
</Target>
<Target Name="_JabReferences" DependsOnTargets="ResolvePackageAssets">
<PropertyGroup>
<_JabAttributesReferenced
Condition="@(PackageDependencies->WithMetadataValue('Identity', 'Jab.Attributes')->Count()) != 0">true</_JabAttributesReferenced>
<DefineConstants Condition="'$(_JabAttributesReferenced)' == 'true'">$(DefineConstants);JAB_ATTRIBUTES_REFERENCED</DefineConstants>
</PropertyGroup>
</Target>
</Project>
14 changes: 14 additions & 0 deletions src/jab.sln
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModuleSample", "samples\Mod
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jab.Roslyn3", "Jab.Roslyn3\Jab.Roslyn3.csproj", "{A6A56D14-EA3A-4D5E-B37A-9B4864E77A28}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jab.Attributes", "Jab.Attributes\Jab.Attributes.csproj", "{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -142,5 +144,17 @@ Global
{A6A56D14-EA3A-4D5E-B37A-9B4864E77A28}.Release|x64.Build.0 = Release|Any CPU
{A6A56D14-EA3A-4D5E-B37A-9B4864E77A28}.Release|x86.ActiveCfg = Release|Any CPU
{A6A56D14-EA3A-4D5E-B37A-9B4864E77A28}.Release|x86.Build.0 = Release|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Debug|x64.ActiveCfg = Debug|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Debug|x64.Build.0 = Debug|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Debug|x86.ActiveCfg = Debug|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Debug|x86.Build.0 = Debug|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Release|Any CPU.Build.0 = Release|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Release|x64.ActiveCfg = Release|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Release|x64.Build.0 = Release|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Release|x86.ActiveCfg = Release|Any CPU
{7ADE331F-90FC-4AF4-83CA-70471A6F0D54}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Loading