private void Report(DiagnosticDescriptor descriptor) { if (_location == null) { var location = _attribute.ApplicationSyntaxReference !.GetSyntax().GetLocation(); _location = Location.Create(_root.SyntaxTree.FilePath, location.SourceSpan, location.GetLineSpan().Span); } var diagnostic = Diagnostic.Create(descriptor, _location); _context.ReportDiagnostic(diagnostic); }
private void Execute(GeneratorContext context) { try { var roots = new ServiceProviderBuilder(context).BuildRoots(); foreach (var root in roots) { var codeWriter = new CodeWriter(); codeWriter.UseNamespace("Jab"); codeWriter.UseNamespace("System"); codeWriter.UseNamespace("System.Diagnostics"); codeWriter.UseNamespace("System.Diagnostics.CodeAnalysis"); codeWriter.Line($"using static Jab.JabHelpers;"); using (root.Type.ContainingNamespace.IsGlobalNamespace ? default : codeWriter.Namespace($"{root.Type.ContainingNamespace.ToDisplayString()}")) { // TODO: implement infinite nesting using CodeWriter.CodeWriterScope? parentTypeScope = root.Type.ContainingType is {} containingType? codeWriter.Scope($"{SyntaxFacts.GetText(containingType.DeclaredAccessibility)} partial class {containingType.Name}") : null; codeWriter.Append($"{SyntaxFacts.GetText(root.Type.DeclaredAccessibility)} partial class {root.Type.Name}"); WriteInterfaces(codeWriter, root, false); using (codeWriter.Scope()) { codeWriter.Line($"private Scope? _rootScope;"); WriteCacheLocations(root, codeWriter, isScope: false); foreach (var rootService in root.RootCallSites) { var rootServiceType = rootService.ServiceType; if (rootService.IsMainImplementation) { codeWriter.Append($"{rootServiceType} IServiceProvider<{rootServiceType}>.GetService()"); } else { codeWriter.Append($"private {rootServiceType} {GetResolutionServiceName(rootService)}()"); } if (rootService.Lifetime == ServiceLifetime.Scoped) { codeWriter.Line($" => GetRootScope().GetService<{rootServiceType}>();"); } else { codeWriter.Line(); using (codeWriter.Scope()) { GenerateCallSiteWithCache(codeWriter, "this", rootService, (w, v) => w.Line($"return {v};")); } } codeWriter.Line(); } WriteServiceProvider(codeWriter, root); WriteDispose(codeWriter, root, isScoped: false); codeWriter.Line($"[DebuggerHidden]"); codeWriter.Line($"public T GetService<T>() => this is IServiceProvider<T> provider ? provider.GetService() : throw CreateServiceNotFoundException<T>();"); codeWriter.Line(); codeWriter.Line($"public Scope CreateScope() => new Scope(this);"); codeWriter.Line(); if (root.KnownTypes.IServiceScopeFactoryType != null) { codeWriter.Line($"{root.KnownTypes.IServiceScopeType} {root.KnownTypes.IServiceScopeFactoryType}.CreateScope() => this.CreateScope();"); codeWriter.Line(); } codeWriter.Append($"public partial class Scope"); WriteInterfaces(codeWriter, root, true); using (codeWriter.Scope()) { WriteCacheLocations(root, codeWriter, isScope: true); codeWriter.Line($"private {root.Type} _root;"); codeWriter.Line(); using (codeWriter.Scope($"public Scope({root.Type} root)")) { codeWriter.Line($"_root = root;"); } codeWriter.Line(); codeWriter.Line($"[DebuggerHidden]"); codeWriter.Line($"public T GetService<T>() => this is IServiceProvider<T> provider ? provider.GetService() : throw CreateServiceNotFoundException<T>();"); codeWriter.Line(); foreach (var rootService in root.RootCallSites) { var rootServiceType = rootService.ServiceType; using (rootService.IsMainImplementation ? codeWriter.Scope($"{rootServiceType} IServiceProvider<{rootServiceType}>.GetService()") : codeWriter.Scope($"private {rootServiceType} {GetResolutionServiceName(rootService)}()")) { if (rootService.Lifetime == ServiceLifetime.Singleton) { codeWriter.Append($"return "); WriteResolutionCall(codeWriter, rootService, "_root"); codeWriter.Line($";"); } else { GenerateCallSiteWithCache(codeWriter, "_root", rootService, (w, v) => w.Line($"return {v};")); } } codeWriter.Line(); } WriteServiceProvider(codeWriter, root); if (root.KnownTypes.IServiceScopeType != null) { codeWriter.Line($"{root.KnownTypes.IServiceProviderType} {root.KnownTypes.IServiceScopeType}.ServiceProvider => this;"); codeWriter.Line(); } WriteDispose(codeWriter, root, isScoped: true); } using (codeWriter.Scope($"private Scope GetRootScope()")) { codeWriter.Line($"if (_rootScope == default)"); codeWriter.Line($"lock (this)"); using (codeWriter.Scope($"if (_rootScope == default)")) { codeWriter.Line($"_rootScope = CreateScope();"); } codeWriter.Line($"return _rootScope;"); } } } context.AddSource($"{root.Type.Name}.Generated.cs", codeWriter.ToString()); } } catch (Exception e) { context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.UnexpectedErrorDescriptor, Location.None, e.ToString())); } }