private static void HandleFieldOrProperty(SyntaxNodeAnalysisContext context, FieldOrProperty fieldOrProperty)
        {
            using (var assignedValues = AssignedValueWalker.Borrow(fieldOrProperty.Symbol, context.SemanticModel, context.CancellationToken))
            {
                using (var recursive = RecursiveValues.Borrow(assignedValues, context.SemanticModel, context.CancellationToken))
                {
                    if (Disposable.IsAnyCreation(recursive, context.SemanticModel, context.CancellationToken).IsEither(Result.Yes, Result.AssumeYes))
                    {
                        if (Disposable.IsAnyCachedOrInjected(recursive, context.SemanticModel, context.CancellationToken).IsEither(Result.Yes, Result.AssumeYes) ||
                            IsMutableFromOutside(fieldOrProperty))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(IDISP008DontMixInjectedAndCreatedForMember.Descriptor, context.Node.GetLocation()));
                        }
                        else if (context.Node.TryFirstAncestorOrSelf <TypeDeclarationSyntax>(out var typeDeclaration) &&
                                 DisposableMember.IsDisposed(fieldOrProperty, typeDeclaration, context.SemanticModel, context.CancellationToken).IsEither(Result.No, Result.AssumeNo) &&
                                 !TestFixture.IsAssignedAndDisposedInSetupAndTearDown(fieldOrProperty, typeDeclaration, context.SemanticModel, context.CancellationToken))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(IDISP002DisposeMember.Descriptor, context.Node.GetLocation()));

                            if (!DisposeMethod.TryFindFirst(fieldOrProperty.ContainingType, context.Compilation, Search.TopLevel, out _) &&
                                !TestFixture.IsAssignedInSetUp(fieldOrProperty, typeDeclaration, context.SemanticModel, context.CancellationToken, out _))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(IDISP006ImplementIDisposable.Descriptor, context.Node.GetLocation()));
                            }
                        }
                    }
                }
            }
        }
Example #2
0
        internal static DisposeWalker Borrow(ITypeSymbol type, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (type.IsAssignableTo(KnownSymbol.IDisposable, semanticModel.Compilation) &&
                DisposeMethod.TryFindFirst(type, semanticModel.Compilation, Search.Recursive, out var disposeMethod))
            {
                return(Borrow(disposeMethod, semanticModel, cancellationToken));
            }

            return(Borrow(() => new DisposeWalker()));
        }
        internal static Result IsArgumentDisposedByReturnValue(ArgumentSyntax argument, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <SyntaxNode> visited = null)
        {
            if (argument?.Parent is ArgumentListSyntax argumentList)
            {
                if (argumentList.Parent is InvocationExpressionSyntax invocation &&
                    semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method)
                {
                    if (method.ContainingType.DeclaringSyntaxReferences.Length == 0)
                    {
                        return(method.ReturnsVoid ||
                               !IsAssignableFrom(method.ReturnType, semanticModel.Compilation)
                            ? Result.No
                            : Result.AssumeYes);
                    }

                    if (method.TryFindParameter(argument, out var parameter))
                    {
                        return(CheckReturnValues(parameter, invocation, semanticModel, cancellationToken, visited));
                    }

                    return(Result.Unknown);
                }

                if (argumentList.Parent is ObjectCreationExpressionSyntax ||
                    argumentList.Parent is ConstructorInitializerSyntax)
                {
                    if (TryGetAssignedFieldOrProperty(argument, semanticModel, cancellationToken, out var member, out var ctor) &&
                        FieldOrProperty.TryCreate(member, out var fieldOrProperty))
                    {
                        var initializer = argument.FirstAncestorOrSelf <ConstructorInitializerSyntax>();
                        if (initializer != null)
                        {
                            if (semanticModel.GetDeclaredSymbolSafe(initializer.Parent, cancellationToken) is IMethodSymbol chainedCtor &&
                                chainedCtor.ContainingType != member.ContainingType)
                            {
                                if (DisposeMethod.TryFindFirst(chainedCtor.ContainingType, semanticModel.Compilation, Search.TopLevel, out var disposeMethod))
                                {
                                    return(DisposableMember.IsDisposed(fieldOrProperty, disposeMethod, semanticModel, cancellationToken)
                                        ? Result.Yes
                                        : Result.No);
                                }
                            }
                        }

                        return(DisposableMember.IsDisposed(fieldOrProperty, ctor.ContainingType, semanticModel, cancellationToken));
                    }

                    if (ctor == null)
                    {
                        return(Result.AssumeYes);
                    }

                    if (ctor.ContainingType.DeclaringSyntaxReferences.Length == 0)
                    {
                        return(IsAssignableFrom(ctor.ContainingType, semanticModel.Compilation) ? Result.AssumeYes : Result.No);
                    }

                    if (ctor.ContainingType.IsAssignableTo(KnownSymbol.NinjectStandardKernel, semanticModel.Compilation))
                    {
                        return(Result.Yes);
                    }

                    return(Result.No);
                }
            }

            return(Result.Unknown);
        }