private void RegisterAnalysis(CompilationStartAnalysisContext context)
        {
            DependencyRegistry dependencyRegistry;

            if (!DependencyRegistry.TryCreateRegistry(context.Compilation, out dependencyRegistry))
            {
                return;
            }

            if (!AnnotationsContext.TryCreate(context.Compilation, out AnnotationsContext annotationsContext))
            {
                return;
            }
            var immutabilityCtx = ImmutabilityContext.Create(context.Compilation, annotationsContext);

            context.RegisterSyntaxNodeAction(
                ctx => AnalyzeInvocation(ctx, immutabilityCtx, dependencyRegistry),
                SyntaxKind.InvocationExpression
                );
        }
        private void AnalyzeInvocation(
            SyntaxNodeAnalysisContext context,
            ImmutabilityContext immutabilityCtx,
            DependencyRegistry registry
            )
        {
            var root = context.Node as InvocationExpressionSyntax;

            if (root == null)
            {
                return;
            }
            var method = context.SemanticModel.GetSymbolInfo(root).Symbol as IMethodSymbol;

            if (method == null)
            {
                return;
            }

            if (!registry.IsRegistationMethod(method))
            {
                return;
            }

            if (IsExpressionInClassInIgnoreList(root, context.SemanticModel))
            {
                return;
            }

            DependencyRegistrationExpression dependencyRegistrationExpresion;

            if (!registry.TryMapRegistrationMethod(
                    method,
                    root.ArgumentList.Arguments,
                    context.SemanticModel,
                    out dependencyRegistrationExpresion
                    ))
            {
                // this can happen where there's a new registration method
                // that we can't map to
                // so we fail
                var diagnostic = Diagnostic.Create(
                    Diagnostics.RegistrationKindUnknown,
                    root.GetLocation()
                    );
                context.ReportDiagnostic(diagnostic);
                return;
            }

            var dependencyRegistration = dependencyRegistrationExpresion.GetRegistration(
                method,
                root.ArgumentList.Arguments,
                context.SemanticModel
                );

            if (dependencyRegistration == null)
            {
                /* This can happen in the following scenarios:
                 * 1) ObjectScope is passed in as a variable and we can't extract it.
                 * 2) Some require argument is missing (compile error).
                 * We fail because we can't analyze it.
                 */
                var diagnostic = Diagnostic.Create(
                    Diagnostics.RegistrationKindUnknown,
                    root.GetLocation()
                    );
                context.ReportDiagnostic(diagnostic);
                return;
            }

            InspectRegistration(dependencyRegistration, immutabilityCtx, context);
        }
        private void InspectRegistration(
            DependencyRegistration registration,
            ImmutabilityContext immutabilityCtx,
            SyntaxNodeAnalysisContext ctx
            )
        {
            if (registration.ObjectScope == ObjectScope.Singleton)
            {
                var typesToInspect = GetTypesRequiredToBeImmutableForSingletonRegistration(registration);
                foreach (var type in typesToInspect)
                {
                    if (type.IsNullOrErrorType())
                    {
                        continue;
                    }

                    // We require full immutability here,
                    // because we don't know if it's a concrete type
                    //
                    // TODO: could make this better by exposing the minimum
                    // scope required for each type

                    var query = new ImmutabilityQuery(
                        ImmutableTypeKind.Total,
                        type
                        );

                    if (!immutabilityCtx.IsImmutable(query, () => null, out var _))
                    {
                        var diagnostic = GetUnsafeSingletonDiagnostic(
                            ctx.Compilation.Assembly,
                            ctx.Node,
                            type
                            );

                        ctx.ReportDiagnostic(diagnostic);
                    }
                }
            }

            // ensure webrequest isn't marked Singleton
            var isMarkedSingleton = registration.DependencyType.IsTypeMarkedSingleton();

            if (isMarkedSingleton && registration.ObjectScope != ObjectScope.Singleton)
            {
                var diagnostic = Diagnostic.Create(
                    Diagnostics.AttributeRegistrationMismatch,
                    ctx.Node.GetLocation(),
                    registration.DependencyType.GetFullTypeNameWithGenericArguments()
                    );
                ctx.ReportDiagnostic(diagnostic);
            }

            if (TryGetInstantiatedTypeForRegistration(registration, out ITypeSymbol instantiatedType))
            {
                if (!TryGetInjectableConstructor(instantiatedType, out IMethodSymbol injectableConstructor))
                {
                    var diagnostic = Diagnostic.Create(
                        Diagnostics.DependencyRegistraionMissingPublicConstructor,
                        ctx.Node.GetLocation(),
                        instantiatedType.GetFullTypeNameWithGenericArguments()
                        );
                    ctx.ReportDiagnostic(diagnostic);
                }
            }
        }