Example #1
0
 public InstanceSourcesScope(IReadOnlyDictionary <ITypeSymbol, InstanceSource> instanceSource, Compilation compilation)
 {
     _instanceSource = instanceSource;
     _containerScope = this;
     _task1Type      = compilation.GetType(typeof(Task <>));
     _valueTask1Type = compilation.GetType(typeof(ValueTask <>));
     Depth           = 0;
 }
Example #2
0
 private InstanceSourcesScope(InstanceSourcesScope containerScope, Dictionary <ITypeSymbol, DelegateParameter> delegateParameters, int depth)
 {
     _instanceSource     = containerScope._instanceSource;
     _delegateParameters = delegateParameters;
     _containerScope     = containerScope;
     _task1Type          = containerScope._task1Type;
     _valueTask1Type     = containerScope._valueTask1Type;
     Depth = depth;
 }
 public static string GenerateContainerImplementations(
     INamedTypeSymbol container,
     InstanceSourcesScope containerScope,
     WellKnownTypes wellKnownTypes,
     Action <Diagnostic> reportDiagnostic,
     CancellationToken cancellationToken) => new ContainerGenerator(
     container,
     containerScope,
     wellKnownTypes,
     reportDiagnostic,
     cancellationToken).GenerateContainerImplementations();
Example #4
0
 private InstanceSourcesScope(InstanceSourcesScope containerScope, Dictionary <ITypeSymbol, DelegateParameter> delegateParameters, int depth)
 {
     _instanceSources = containerScope._instanceSources;
     _genericRegistrationsResolver = containerScope._genericRegistrationsResolver;
     _decoratorSources             = containerScope._decoratorSources;
     _genericDecoratorsResolver    = containerScope._genericDecoratorsResolver;
     _wellKnownTypes     = containerScope._wellKnownTypes;
     _containerScope     = containerScope;
     _delegateParameters = delegateParameters;
     Depth = depth;
 }
Example #5
0
 public InstanceSourcesScope(
     IReadOnlyDictionary <ITypeSymbol, InstanceSources> instanceSources,
     GenericRegistrationsResolver genericRegistrationsResolver,
     IReadOnlyDictionary <ITypeSymbol, ImmutableArray <DecoratorSource> > decoratorSources,
     GenericDecoratorsResolver genericDecoratorsResolver,
     WellKnownTypes wellKnownTypes)
 {
     _instanceSources = instanceSources;
     _genericRegistrationsResolver = genericRegistrationsResolver;
     _decoratorSources             = decoratorSources;
     _genericDecoratorsResolver    = genericDecoratorsResolver;
     _wellKnownTypes = wellKnownTypes;
     _containerScope = this;
     Depth           = 0;
 }
        public static bool HasCircularOrMissingDependencies(ITypeSymbol target, bool isAsync, InstanceSourcesScope containerScope, Action <Diagnostic> reportDiagnostic, Location location)
        {
            var currentlyVisiting = new HashSet <InstanceSource>();
            var visited           = new HashSet <InstanceSource>();

            return(Visit(
                       GetInstanceSourceOrReport(target, containerScope),
                       containerScope,
                       usedParams: null,
                       isScopeAsync: isAsync));

            InstanceSource?GetInstanceSourceOrReport(ITypeSymbol type, InstanceSourcesScope instanceSourcesScope)
            {
                if (!instanceSourcesScope.TryGetSource(type, out var instanceSource, out var ambiguous, out var sourcesNotMatchingConstraints))
                {
                    if (ambiguous)
                    {
                        reportDiagnostic(NoBestSourceForType(location, target, type));
                    }
                    else
                    {
                        reportDiagnostic(NoSourceForType(location, target, type));

                        foreach (var sourceNotMatchingConstraints in sourcesNotMatchingConstraints)
                        {
                            reportDiagnostic(WarnFactoryMethodNotMatchingConstraint(location, target, type, sourceNotMatchingConstraints));
                        }
                    }
                    return(null);
                }
                return(instanceSource);
            }

            // returns true if has any errors that make resolution impossible
            bool Visit(InstanceSource?instanceSource, InstanceSourcesScope instanceSourcesScope, HashSet <IParameterSymbol>?usedParams, bool isScopeAsync)
            {
                if (instanceSource is null)
                {
                    return(true);
                }

                var outerIsContainerScope = ReferenceEquals(instanceSourcesScope, containerScope);
                var innerIsContainerScope = outerIsContainerScope;

                if (outerIsContainerScope && visited.Contains(instanceSource))
                {
                    return(false);
                }

                if (!currentlyVisiting.Add(instanceSource))
                {
                    reportDiagnostic(CircularDependency(location, target, instanceSource.OfType));
                    return(true);
                }

                var result = false;

                instanceSourcesScope  = instanceSourcesScope.Enter(instanceSource);
                innerIsContainerScope = ReferenceEquals(instanceSourcesScope, containerScope);
                if (innerIsContainerScope && visited.Contains(instanceSource))
                {
                    return(false);
                }

                if (currentlyVisiting.Count > MAX_DEPENDENCY_TREE_DEPTH)
                {
                    reportDiagnostic(DependencyTreeTooDeep(location, target));
                    return(true);
                }

                switch (instanceSource)
                {
                case DelegateSource(var delegateType, var returnType, var delegateParameters, var isAsync) delegateSource:
                {
                    foreach (var paramsWithType in delegateParameters.GroupBy(x => x.Type))
                    {
                        if (paramsWithType.Count() > 1)
                        {
                            reportDiagnostic(DelegateHasMultipleParametersOfTheSameType(location, target, instanceSource.OfType, paramsWithType.Key));
                            result = true;
                        }
                    }

                    var returnTypeSource = GetInstanceSourceOrReport(returnType, instanceSourcesScope);

                    if (returnTypeSource is DelegateParameter {
                            Parameter : var param
                        })
                    {
                        if (delegateParameters.Contains(param))
                        {
                            reportDiagnostic(WarnDelegateReturnTypeProvidedBySameDelegate(location, target, instanceSource.OfType, returnType));
                        }
                        else
                        {
                            reportDiagnostic(WarnDelegateReturnTypeProvidedByAnotherDelegate(location, target, instanceSource.OfType, returnType));
                        }
                    }
        public static bool HasCircularOrMissingDependencies(ITypeSymbol target, bool isAsync, InstanceSourcesScope containerScope, Action <Diagnostic> reportDiagnostic, Location location)
        {
            var currentlyVisiting = new HashSet <ITypeSymbol>();
            var visited           = new HashSet <ITypeSymbol>();

            return(Visit(
                       target,
                       containerScope,
                       usedParams: null,
                       isScopeAsync: isAsync));

            // returns true if it has errors
            bool Visit(ITypeSymbol node, InstanceSourcesScope instanceSourcesScope, HashSet <IParameterSymbol>?usedParams, bool isScopeAsync)
            {
                var outerIsContainerScope = ReferenceEquals(instanceSourcesScope, containerScope);
                var innerIsContainerScope = outerIsContainerScope;

                if (outerIsContainerScope && visited.Contains(node))
                {
                    return(false);
                }

                if (!currentlyVisiting.Add(node))
                {
                    reportDiagnostic(CircularDependency(location, target, node));
                    return(true);
                }

                var result = false;

                if (!instanceSourcesScope.TryGetSource(node, out var instanceSource))
                {
                    reportDiagnostic(NoSourceForType(location, target, node));
                    result = true;
                }
                else
                {
                    instanceSourcesScope  = instanceSourcesScope.Enter(instanceSource);
                    innerIsContainerScope = ReferenceEquals(instanceSourcesScope, containerScope);
                    if (innerIsContainerScope && visited.Contains(node))
                    {
                        return(false);
                    }

                    switch (instanceSource)
                    {
                    case DelegateSource(var delegateType, var returnType, var delegateParameters, var isAsync) delegateSource:
                    {
                        foreach (var paramsWithType in delegateParameters.GroupBy(x => x.Type))
                        {
                            if (paramsWithType.Count() > 1)
                            {
                                reportDiagnostic(DelegateHasMultipleParametersOfTheSameType(location, target, node, paramsWithType.Key));
                                result = true;
                            }
                        }

                        if (instanceSourcesScope.TryGetSource(returnType, out var returnTypeSource))
                        {
                            if (returnTypeSource is DelegateParameter {
                                    parameter : var param
                                })
                            {
                                if (delegateParameters.Contains(param))
                                {
                                    reportDiagnostic(DelegateReturnTypeProvidedBySameDelegate(location, target, node, returnType));
                                }
                                else
                                {
                                    reportDiagnostic(DelegateReturnTypeProvidedByAnotherDelegate(location, target, node, returnType));
                                }
                            }