Пример #1
0
        private static bool IsArgumentInConstructorOfTrackingType(CustomAnalysisContext context,
                                                                  string localVariableName, SyntaxNode parentScope)
        {
            return(parentScope
                   .DescendantNodes <ObjectCreationExpressionSyntax>()
                   .Any(oce =>
            {
                var argumentListSyntax = oce.ArgumentList;
                if (argumentListSyntax == null)
                {
                    return false;
                }
                return argumentListSyntax.Arguments.Any(arg =>
                {
                    var expression = arg.Expression as IdentifierNameSyntax;
                    var isPartOfObjectCreation = expression?.Identifier.Text == localVariableName;
                    if (!isPartOfObjectCreation)
                    {
                        return false;
                    }

                    //check if is tracking instance
                    var sym = context.SemanticModel.GetSymbolInfo(oce);
                    return (sym.Symbol as IMethodSymbol)?.ReceiverType is INamedTypeSymbol type2 &&
                    Detector.IsTrackedType(type2, oce, context.SemanticModel);
                });
            }));
        }
Пример #2
0
 internal static bool IsTrackedViaTrackingMethod(this SyntaxNode node, CustomAnalysisContext context, BaseMethodDeclarationSyntax scope,
                                                 string variableName)
 {
     return(scope
            .DescendantNodes <InvocationExpressionSyntax>()
            .Any(ies => ies.IsInvocationExpressionSyntaxOn(variableName) && context.Detector.IsTrackingMethodCall(ies, context.SemanticModel)));
 }
Пример #3
0
        private static bool IsCallToMethodThatIsConsideredAsDisposeCall(IEnumerable <InvocationExpressionSyntax> invocations,
                                                                        CustomAnalysisContext context)
        {
            var fullName = GetReturnOrReceivedType(context);

            return(Configuration.DisposingMethodsAtSpecialClasses.TryGetValue(fullName, out var methodCalls) &&
                   methodCalls.Any(mc => invocations.Any(ies => ies.IsCallToMethod(mc))));
        }
Пример #4
0
        private static void AnalyzeInvocationExpressionInsideAwaitExpression(CustomAnalysisContext context)
        {
            var node                = context.Node;
            var awaitExpression     = node.Parent as AwaitExpressionSyntax;
            var awaitExpressionInfo = context.SemanticModel.GetAwaitExpressionInfo(awaitExpression);

            if (!(awaitExpressionInfo.GetResultMethod?.ReturnType is INamedTypeSymbol returnType))
            {
                return;
            }
            if (!returnType.IsDisposableOrImplementsDisposable())
            {
                return;
            }
            if (Detector.IsIgnoredTypeOrImplementsIgnoredInterface(returnType))
            {
                return;
            }
            if (awaitExpression.IsDescendantOfUsingHeader())
            {
                return;
            }
            if (awaitExpression.IsPartOfVariableDeclaratorInsideAUsingDeclaration())
            {
                return;
            }
            if (awaitExpression.IsPartOfReturnStatementInMethod())
            {
                return;
            }
            if (awaitExpression.IsReturnedLaterWithinMethod())
            {
                return;
            }
            if (awaitExpression.IsDescendantOfVariableDeclarator())
            {
                AnalyzeNodeWithinVariableDeclarator(context.NewWith(awaitExpression));
            }
            else if (awaitExpression.IsDescendantOfAssignmentExpressionSyntax())
            {
                if (node.TryFindParentClass(out var @class))
                {
                    var assignment = awaitExpression?.Parent as AssignmentExpressionSyntax;
                    var member     = (assignment?.Left as IdentifierNameSyntax)?.Identifier.Text;
                    var isDisposed = @class.ContainsDisposeCallFor(member, context.SemanticModel, Configuration);
                    if (isDisposed)
                    {
                        return;
                    }
                }
                context.ReportNotDisposedLocalVariable();
            }
            else
            {
                context.ReportNotDisposedAnonymousObject();
            }
        }
Пример #5
0
        private static void AnalyzeNodeWithinLocalDeclaration(CustomAnalysisContext context, string localVariableName)
        {
            if (!context.Node.TryFindParentScope(out var parentScope))
            {
                return;
            }

            var localVariableInsideUsing = parentScope
                                           .DescendantNodes <UsingStatementSyntax>()
                                           .SelectMany(@using => @using.DescendantNodes <IdentifierNameSyntax>())
                                           .Where(id => localVariableName != null && (string)id.Identifier.Value == localVariableName)
                                           .ToArray();

            if (localVariableInsideUsing.Any())
            {
                if (localVariableInsideUsing.Any(id => id.Parent is UsingStatementSyntax)) //using(mem))
                {
                    return;
                }
                if (IsArgumentInConstructorOfTrackingTypeWithinUsing(context, localVariableInsideUsing))
                {
                    return;
                }

                context.ReportNotDisposedLocalVariable();
                return;
            }
            var invocationExpressions = parentScope.DescendantNodes <InvocationExpressionSyntax>().ToArray();

            if (invocationExpressions.Any(ie => ie.IsInterlockedExchangeAssignExpressionFor(localVariableName)))
            {
                return;
            }
            if (ExistsDisposeCall(localVariableName, invocationExpressions, context.SemanticModel))
            {
                return;
            }
            if (IsArgumentInTrackingMethod(context, localVariableName, invocationExpressions))
            {
                return;
            }
            if (IsArgumentInConstructorOfTrackingType(context, localVariableName, parentScope))
            {
                return;
            }
            if (IsCallToMethodThatIsConsideredAsDisposeCall(invocationExpressions, context))
            {
                return;
            }

            context.ReportNotDisposedLocalVariable();
        }
Пример #6
0
        private static bool IsArgumentInConstructorOfTrackingTypeWithinUsing(CustomAnalysisContext context, IEnumerable <IdentifierNameSyntax> localVariableInsideUsing)
        {
            return(localVariableInsideUsing
                   .Select(id => id.Parent?.Parent?.Parent)
                   .Where(parent => parent is ObjectCreationExpressionSyntax)
                   .Cast <ObjectCreationExpressionSyntax>()
                   .Any(ocs =>
            {
                var sym = context.SemanticModel.GetSymbolInfo(ocs);
                var type2 = (sym.Symbol as IMethodSymbol)?.ReceiverType as INamedTypeSymbol;

                return Detector.IsTrackedType(type2, ocs, context.SemanticModel);
            }));
        }
Пример #7
0
        private static void CheckIfObjectCreationTracksNode(CustomAnalysisContext context, ObjectCreationExpressionSyntax objectCreation)
        {
            var t = context.SemanticModel.GetReturnTypeOf(objectCreation);

            if (t == null)
            {
                return;           //return type could not be determined
            }
            if (Detector.IsTrackedType(t, objectCreation, context.SemanticModel))
            {
                return;
            }

            context.ReportNotDisposedAnonymousObject();
        }
Пример #8
0
        private static void AnalyzePartOfMethodCall(CustomAnalysisContext ctx)
        {
            var methodInvocation = ctx.Node.Parent.Parent.Parent as InvocationExpressionSyntax;

            if (Detector.IsTrackingMethodCall(methodInvocation, ctx.Context.SemanticModel))
            {
                return;
            }

            if (methodInvocation.IsInterlockedExchangeExpression())
            {
                return;
            }

            ctx.ReportNotDisposedAnonymousObject();
        }
Пример #9
0
        private static void AnalyzeNodeInArgumentList(CustomAnalysisContext context)
        {
            var objectCreation = context.Node.Parent.Parent.Parent as ObjectCreationExpressionSyntax;
            var t = context.SemanticModel.GetReturnTypeOf(objectCreation);

            if (t == null)
            {
                return;           //return type could not be determined
            }
            if (Detector.IsTrackedType(t, objectCreation, context.SemanticModel))
            {
                return;
            }

            context.ReportNotDisposedAnonymousObject();
        }
Пример #10
0
        private static string GetReturnOrReceivedType(CustomAnalysisContext context)
        {
            var node     = context.OriginalNode;
            var typeInfo = context.SemanticModel.GetSymbolInfo(node);

            switch (node)
            {
            case ObjectCreationExpressionSyntax _:
                return(((typeInfo.Symbol as IMethodSymbol)?.ReceiverType as INamedTypeSymbol).GetFullNamespace());

            case InvocationExpressionSyntax _:
                return(((typeInfo.Symbol as IMethodSymbol)?.ReturnType as INamedTypeSymbol).GetFullNamespace());

            default:
                throw new ArgumentException($"Unexpected Node Type: '{node.GetType()}'");
            }
        }
        private static void AnalyzeObjectCreationExpressionStatement(SyntaxNodeAnalysisContext context)
        {
            if (!(context.Node is ObjectCreationExpressionSyntax node))
            {
                return;                                                         //something went wrong
            }
            var symbolInfo = context.SemanticModel.GetSymbolInfo(node);
            var t          = (symbolInfo.Symbol as IMethodSymbol)?.ReceiverType as INamedTypeSymbol;
            var ctx        = CustomAnalysisContext.WithOriginalNode(context, DisposableSource.ObjectCreation, t, Detector, Configuration);

            if (!ctx.CouldDetectType())
            {
            }
            else if (!ctx.IsDisposableOrImplementsDisposable())
            {
                return;
            }
            else if (node.IsParentADisposeCallIgnoringParenthesis())
            {
                return;                                                      //(new MemoryStream()).Dispose()
            }
            else if (Detector.IsIgnoredTypeOrImplementsIgnoredInterface(ctx.Type))
            {
            }
            else if (node.IsReturnedInProperty())
            {
                AnalyzeNodeInReturnStatementOfProperty(ctx);
            }
            else if (node.IsPartOfReturnStatementInBlock())
            {
                AnalyzeForHiddenDisposables(node, ctx);
            } // return new MemoryStream() or return Task.FromResult(new MemoryStream())
            else if (node.IsArrowExpressionClauseOfMethod())// void/IDisposable/object Create()=>CreateMemoryStream()
            {
                AnalyzeArrowExpressionOfMethod(ctx);
            }
            else if (node.IsArrowExpressionClauseOfLocalFunction())
            {
                AnalyzeArrowExpressionOfLocalFunction(ctx);
            }
            else if (node.IsPartOfLocalFunction(out var localFunctionStatement) && node.IsReturnedValue())
            {
                var returnTypeSyntax = localFunctionStatement.ReturnType;
                var returnType       = ctx.SemanticModel.GetSymbolInfo(returnTypeSyntax);
            }
Пример #12
0
        private static void AnalyzeNodeWithinVariableDeclarator(CustomAnalysisContext context)
        {
            var node       = context.Node;
            var identifier = node.GetIdentifierIfIsPartOfVariableDeclarator();//getIdentifier

            if (identifier == null)
            {
                return;
            }
            if (node.IsLocalDeclaration()) //var m = new MemoryStream();
            {
                AnalyzeNodeWithinLocalDeclaration(context, identifier);
            }
            else if (node.IsFieldDeclaration()) //_field = new MemoryStream();
            {
                AnalyzeNodeInFieldDeclaration(context, identifier);
            }
        }
Пример #13
0
        private static void AnalyzeNodeInAutoPropertyOrPropertyExpressionBody(CustomAnalysisContext context)
        {
            var node = context.Node;

            if (!(node.Parent.Parent is PropertyDeclarationSyntax propertyDeclaration))
            {
                return;                                                                         // should not happen => we cke this before
            }
            if (node.IsDisposedInDisposingMethod(propertyDeclaration.Identifier.Text, Configuration, context.SemanticModel))
            {
                return;
            }
            if (propertyDeclaration.IsStatic())
            {
                context.ReportNotDisposedStaticProperty(propertyDeclaration.Identifier.Text);
            }
            else
            {
                context.ReportNotDisposedProperty(propertyDeclaration.Identifier.Text);
            }
        }
Пример #14
0
        private static void ReportStaticOrNonStaticNotDisposedMember(CustomAnalysisContext context, string variableName)
        {
            var node            = context.Node;
            var containingClass = node.FindContainingClass();

            if (containingClass == null)
            {
                return;
            }
            var fieldDeclarationSyntax = containingClass.FindFieldNamed(variableName);

            if (fieldDeclarationSyntax != null)
            {
                if (fieldDeclarationSyntax.IsStatic())
                {
                    context.ReportNotDisposedStaticField(variableName);
                }
                else
                {
                    context.ReportNotDisposedField(variableName);
                }
            }
            else
            {
                var prop = containingClass.FindPropertyNamed(variableName);
                if (prop == null)
                {
                    return;               //this should never happen
                }
                if (prop.IsStatic())
                {
                    context.ReportNotDisposedStaticProperty(variableName);
                }
                else
                {
                    context.ReportNotDisposedProperty(variableName);
                }
            }
        }
Пример #15
0
        private static void AnalyzeNodeInFieldDeclaration(CustomAnalysisContext context,
                                                          string fieldName)
        {
            if (context.Node.IsDisposedInDisposingMethod(fieldName, Configuration, context.SemanticModel))
            {
                return;
            }

            var containeringClass = context.Node.FindContainingClass();
            var fieldDeclaration  = containeringClass?.FindFieldNamed(fieldName);

            if (fieldDeclaration == null)
            {
                return;
            }
            if (fieldDeclaration.IsStatic())
            {
                context.ReportNotDisposedStaticField(fieldName);
            }
            else
            {
                context.ReportNotDisposedField(fieldName);
            }
        }
Пример #16
0
 private static bool IsArgumentInTrackingMethod(CustomAnalysisContext context, string localVariableName, IEnumerable <InvocationExpressionSyntax> invocationExpressions)
 {
     return(invocationExpressions.Any(ie => ie.UsesVariableInArguments(localVariableName) && Detector.IsTrackingMethodCall(ie, context.SemanticModel)));
 }
Пример #17
0
        private static void AnalyzeNodeInAssignmentExpression(CustomAnalysisContext context)
        {
            var node = context.Node;
            //is local or global variable
            var assignmentExpressionSyntax = node.Parent as AssignmentExpressionSyntax;
            var variableName = (assignmentExpressionSyntax?.Left as IdentifierNameSyntax)?.Identifier.Text;

            if (node.TryFindContainingMethod(out var containingMethod))
            {
                if (containingMethod.ContainsDisposeCallFor(variableName, context.SemanticModel, Configuration))
                {
                    return;
                }

                if (containingMethod.HasDecendentVariableDeclaratorFor(variableName))
                {
                    //local declaration in method
                    if (containingMethod.Returns(variableName))
                    {
                        return;
                    }
                    if (node.IsDescendantOfUsingHeader())
                    {
                        return;
                    }
                    if (node.IsArgumentInObjectCreation())
                    {
                        AnalyzeNodeInArgumentList(context);
                        return;
                    }

                    if (containingMethod.HasInterlockedExchangeWith(variableName))
                    {
                        return;
                    }
                    //is part of tracking call
                    context.ReportNotDisposedLocalVariable();
                    return;
                }
                if (node.IsDisposedInDisposingMethod(variableName, Configuration, context.SemanticModel))
                {
                    return;
                }
                if (node.IsArgumentInObjectCreation())
                {
                    AnalyzeNodeInArgumentList(context);
                    return;
                }

                //assignment to field or property
                ReportStaticOrNonStaticNotDisposedMember(context, variableName);

                return;
            }

            if (node.TryFindContainingCtor(out var ctor))
            {
                if (ctor.HasDecendentVariableDeclaratorFor(variableName))
                {
                    //local variable in ctor
                    if (ctor.HasInterlockedExchangeWith(variableName))
                    {
                        return;
                    }
                    if (node.IsDescendantOfUsingHeader())
                    {
                        return;
                    }
                    if (node.IsArgumentInObjectCreation())
                    {
                        AnalyzeNodeInArgumentList(context);
                        return;
                    }
                    if (ctor.ContainsDisposeCallFor(variableName, context.SemanticModel, Configuration))
                    {
                        return;
                    }
                    context.ReportNotDisposedLocalVariable();
                }
                else //field or property
                {
                    if (node.IsDisposedInDisposingMethod(variableName, Configuration, context.SemanticModel))
                    {
                        return;
                    }

                    if (node.IsAssignmentToProperty(variableName, out var isStatic))
                    {
                        if (isStatic)
                        {
                            context.ReportNotDisposedStaticProperty(variableName);
                        }
                        else
                        {
                            context.ReportNotDisposedProperty(variableName);
                        }
                    }
                    else
                    {
                        if (node.IsAssignmentToStaticField(variableName))
                        {
                            context.ReportNotDisposedStaticField(variableName);
                        }
                        else
                        {
                            context.ReportNotDisposedField(variableName);
                        }
                    }
                }
            }
        }
Пример #18
0
        private static void AnalyzeInvocationExpressionStatement(SyntaxNodeAnalysisContext context)
        {
            if (!(context.Node is InvocationExpressionSyntax node))
            {
                return;
            }

            var symbolInfo = context.SemanticModel.GetSymbolInfo(node);
            var symbol     = symbolInfo.Symbol as IMethodSymbol;

            var type = symbol?.ReturnType as INamedTypeSymbol;
            var ctx  = CustomAnalysisContext.WithOriginalNode(context, DisposableSource.InvocationExpression, type, Detector, Configuration);

            if (!ctx.CouldDetectType())
            {
            }
            else if (node.IsParentADisposeCallIgnoringParenthesis())
            {
                return;                                                      //(new object()).AsDisposable().Dispose()
            }
            else if (node.IsPartOfAwaitExpression())
            {
                AnalyzeInvocationExpressionInsideAwaitExpression(ctx);
            }
            else if (!ctx.IsDisposableOrImplementsDisposable())
            {
                return;
            }
            else if (node.IsReturnedInProperty())
            {
                AnalyzeNodeInReturnStatementOfProperty(ctx);
            }
            else if (ctx.IsTypeIgnoredOrImplementsIgnoredInterface())
            {
            }                                                             //GetEnumerator()
            else if (Detector.IsTrackingMethodCall(node, context.SemanticModel))
            {
            }                                                                       //ignored extension methods
            else if (Detector.IsIgnoredFactoryMethod(node, context.SemanticModel))
            {
                return;                                                                    //A.Fake<IDisposable>
            }
            else if (node.IsMaybePartOfMethodChainUsingTrackingExtensionMethod())
            {
                //there maybe multiple method invocations within one chain
                var baseNode = node;
                while (baseNode?.Parent is MemberAccessExpressionSyntax && baseNode?.Parent?.Parent is InvocationExpressionSyntax parentIes)
                {
                    baseNode = parentIes;
                    if (Detector.IsTrackingMethodCall(baseNode, context.SemanticModel))
                    {
                        return;
                    }
                }
            }
            else if (node.IsPartOfMethodCall())
            {
                AnalyzePartOfMethodCall(ctx);
            }
            else if (node.IsPartOfReturnStatementInBlock())
            {
            }                                                   // return new MemoryStream() or return Task.FromResult(new MemoryStream())
            else if (node.IsPartOfYieldReturnStatementInBlock())
            {
            }                                                        //yield return CreateMemoryStream()
            else if (node.IsArrowExpressionClauseOfMethod())
            {
            }                                                    // void Create()=>new MemoryStream()
            else if (node.IsReturnValueInLambdaExpression())
            {
            }                                                    //e.g. ()=> new MemoryStream
            else if (node.IsReturnedLaterWithinMethod())
            {
            }
            else if (node.IsReturnedLaterWithinParenthesizedLambdaExpression())
            {
            }
            else if (node.IsArgumentInObjectCreation())
            {
                AnalyzeNodeInArgumentList(ctx);
            }
            else if (node.IsPartIfArrayInitializerThatIsPartOfObjectCreation())
            {
                var objectCreation = node.Parent.Parent.Parent.Parent.Parent as ObjectCreationExpressionSyntax;
                CheckIfObjectCreationTracksNode(ctx, objectCreation);
            }
            else if (node.IsDescendantOfUsingHeader())
            {
            }                                              //using(memstream) or using(new MemoryStream())
            else if (node.IsDescendantOfVariableDeclarator())
            {
                AnalyzeNodeWithinVariableDeclarator(ctx);
            }
            else if (node.IsPartOfAssignmentExpression())
            {
                AnalyzeNodeInAssignmentExpression(ctx);
            }
            else if (node.IsPartOfAutoProperty())
            {
                AnalyzeNodeInAutoPropertyOrPropertyExpressionBody(ctx);
            }
            else if (node.IsPartOfPropertyExpressionBody())
            {
                AnalyzeNodeInAutoPropertyOrPropertyExpressionBody(ctx);
            }
            else
            {
                ctx.ReportNotDisposedAnonymousObject();  //call to Create(): MemeoryStream
            }
        }
Пример #19
0
        private static void AnalyzeObjectCreationExpressionStatement(SyntaxNodeAnalysisContext context)
        {
            if (!(context.Node is ObjectCreationExpressionSyntax node))
            {
                return;                                                         //something went wrong
            }
            var symbolInfo = context.SemanticModel.GetSymbolInfo(node);
            var t          = (symbolInfo.Symbol as IMethodSymbol)?.ReceiverType as INamedTypeSymbol;
            var ctx        = CustomAnalysisContext.WithOriginalNode(context, DisposableSource.ObjectCreation, t, Detector, Configuration);

            if (!ctx.CouldDetectType())
            {
            }
            else if (!ctx.IsDisposableOrImplementsDisposable())
            {
                return;
            }
            else if (node.IsParentADisposeCallIgnoringParenthesis())
            {
                return;                                                      //(new MemoryStream()).Dispose()
            }
            else if (Detector.IsIgnoredTypeOrImplementsIgnoredInterface(ctx.Type))
            {
            }
            else if (node.IsReturnedInProperty())
            {
                AnalyzeNodeInReturnStatementOfProperty(ctx);
            }
            else if (node.IsPartOfReturnStatementInBlock())
            {
            }                                                   // return new MemoryStream() or return Task.FromResult(new MemoryStream())
            else if (node.IsPartOfYieldReturnStatementInBlock())
            {
            }                                                        //yield return new MemoryStream()
            else if (node.IsArrowExpressionClauseOfMethod())
            {
            }                                                    // void Create()=>CreateMemoryStream()
            else if (node.IsReturnValueInLambdaExpression())
            {
            }
            else if (node.IsReturnedLaterWithinMethod())
            {
            }
            else if (node.IsReturnedLaterWithinParenthesizedLambdaExpression())
            {
            }
            else if (node.IsPartOfMethodCall())
            {
                AnalyzePartOfMethodCall(ctx);
            }
            else if (node.IsMaybePartOfMethodChainUsingTrackingExtensionMethod())
            {
                var methodInvocation = node.Parent.Parent as InvocationExpressionSyntax;
                if (Detector.IsTrackingMethodCall(methodInvocation, context.SemanticModel))
                {
                    return;
                }
            }
            else if (node.IsArgumentInObjectCreation())
            {
                AnalyzeNodeInArgumentList(ctx);
            }
            else if (node.IsPartIfArrayInitializerThatIsPartOfObjectCreation())
            {
                var objectCreation = node.Parent.Parent.Parent.Parent.Parent as ObjectCreationExpressionSyntax;
                CheckIfObjectCreationTracksNode(ctx, objectCreation);
            }
            else if (node.IsDescendantOfUsingHeader())
            {
            }                                             //this have to be checked after IsArgumentInObjectCreation
            else if (node.IsDescendantOfVariableDeclarator())
            {
                AnalyzeNodeWithinVariableDeclarator(ctx);
            }
            else if (node.IsPartOfAssignmentExpression())
            {
                AnalyzeNodeInAssignmentExpression(ctx);
            }
            else if (node.IsPartOfPropertyExpressionBody())
            {
                AnalyzeNodeInAutoPropertyOrPropertyExpressionBody(ctx);
            }
            else if (node.IsPartOfAutoProperty())
            {
                AnalyzeNodeInAutoPropertyOrPropertyExpressionBody(ctx);
            }
            else
            {
                ctx.ReportNotDisposedAnonymousObject();  //new MemoryStream();
            }
        }