Exemplo n.º 1
0
        public static bool IsAccessOnNewlyCreatedObject(KnownSymbols knownSymbols,
                                                        SemanticModel semanticModel,
                                                        SyntaxNode node, RecursiveState recursiveState1)
        {
            bool IsOnNewlyCreatedObject(ExpressionSyntax exp)
            {
                if (exp is MemberAccessExpressionSyntax memberAccess1)
                {
                    return(IsOnNewlyCreatedObject(memberAccess1.Expression));
                }
                if (exp is ElementAccessExpressionSyntax elementAccess1)
                {
                    return(IsOnNewlyCreatedObject(elementAccess1.Expression));
                }
                return(Utils.IsNewlyCreatedObject(semanticModel, exp, knownSymbols, RecursiveIsNewlyCreatedObjectState.Empty(), recursiveState1));
            }

            if (node.Parent is MemberAccessExpressionSyntax memberAccess)
            {
                return(IsOnNewlyCreatedObject(memberAccess));
            }

            if (node is ElementAccessExpressionSyntax elementAccess)
            {
                return(IsOnNewlyCreatedObject(elementAccess));
            }

            return(false);
        }
Exemplo n.º 2
0
 public static bool ReturnsNewObject(PropertyDeclarationSyntax propertyDeclaration,
                                     SemanticModel semanticModel,
                                     KnownSymbols knownSymbols,
                                     RecursiveState recursiveState1)
 {
     return(!GetNonNewObjectReturnsForPropertyGet(propertyDeclaration, semanticModel, knownSymbols, recursiveState1).Any());
 }
Exemplo n.º 3
0
        public static IEnumerable <ExpressionSyntax> GetNonNewObjectReturnsForMethod(
            BaseMethodDeclarationSyntax methodDeclaration,
            SemanticModel semanticModel,
            KnownSymbols knownSymbols, RecursiveState recursiveState1)
        {
            var methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration);

            if (!methodSymbol.ReturnsByRef && IsCompleteValueType(methodSymbol.ReturnType))
            {
                yield break;
            }

            var returnExpressions =
                methodDeclaration.Body != null
                    ? methodDeclaration.Body
                .DescendantNodes()
                .OfType <ReturnStatementSyntax>()
                .Select(x => x.Expression)
                .ToArray()
                    : new[] { methodDeclaration.ExpressionBody.Expression };

            foreach (var expression in returnExpressions)
            {
                if (!Utils.IsNewlyCreatedObject(semanticModel, expression, knownSymbols, RecursiveIsNewlyCreatedObjectState.Empty(), recursiveState1))
                {
                    yield return(expression);
                }
            }
        }
Exemplo n.º 4
0
        private static bool MethodReturnsNewObject(
            SemanticModel semanticModel,
            KnownSymbols knownSymbols,
            RecursiveState recursiveState,
            IMethodSymbol invokedMethod)
        {
            if (invokedMethod.IsInCode() && !invokedMethod.IsAbstract)
            {
                var location = invokedMethod.Locations.First();

                var locationSourceTree = location.SourceTree;

                var node = locationSourceTree.GetRoot().FindNode(location.SourceSpan);

                if (node is BaseMethodDeclarationSyntax methodNode)
                {
                    if (ReturnsNewObject(
                            methodNode,
                            Utils.GetSemanticModel(semanticModel, methodNode.SyntaxTree),
                            knownSymbols, recursiveState))
                    {
                        return(true);
                    }
                }
                else if (node.Parent.Parent is PropertyDeclarationSyntax propertyDeclaration)
                {
                    if (ReturnsNewObject(
                            propertyDeclaration,
                            Utils.GetSemanticModel(semanticModel, propertyDeclaration.SyntaxTree),
                            knownSymbols, recursiveState))
                    {
                        return(true);
                    }
                }
            }
            else
            {
                if (GetAllAttributes(invokedMethod)
                    .Any(x => IsReturnsNewObjectAttribute(x.AttributeClass.Name)))
                {
                    return(true);
                }

                if (knownSymbols.KnownReturnsNewObjectMethods.TryGetValue(
                        Utils.GetFullMetaDataName(invokedMethod.ContainingType), out var methods) &&
                    methods.AnyMatches(invokedMethod))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 5
0
        public static IEnumerable <Impurity> GetImpurities(
            SyntaxNode methodDeclaration,
            SemanticModel semanticModel,
            KnownSymbols knownSymbols,
            RecursiveState recursiveState,
            PurityType purityType = PurityType.Pure,
            Maybe <PureLambdaConfig> pureLambdaConfig = default)
        {
            var impuritiesFinder = new ImpuritiesFinder(semanticModel, purityType, knownSymbols);

            return(impuritiesFinder.GetImpurities(methodDeclaration, recursiveState, pureLambdaConfig));
        }
Exemplo n.º 6
0
        ChangeAcceptedPurityTypeBasedOnWhetherExpressionRepresentsANewObjectOrParameterBasedExpression(
            PurityType currentAcceptedPurityType,
            ExpressionSyntax node,
            KnownSymbols knownSymbols,
            SemanticModel semanticModel,
            RecursiveState recursiveState)
        {
            if (Utils.IsNewlyCreatedObject(semanticModel, node, knownSymbols, RecursiveIsNewlyCreatedObjectState.Empty(), recursiveState))
            {
                return(PurityType.PureExceptLocally);
            }
            else if (ImpuritiesFinder.IsParameter(semanticModel, node))
            {
                return(PurityType.PureExceptReadLocally);
            }

            return(currentAcceptedPurityType);
        }
Exemplo n.º 7
0
        public static bool AnyImpurePropertyInitializer(TypeDeclarationSyntax typeDeclaration,
                                                        SemanticModel semanticModel,
                                                        KnownSymbols knownSymbols,
                                                        RecursiveState recursiveState,
                                                        InstanceStaticCombination instanceStaticCombination)
        {
            var props = typeDeclaration
                        .Members
                        .OfType <PropertyDeclarationSyntax>()
                        .Where(instanceStaticCombination.Matches)
                        .ToArray();

            foreach (var var in props.Select(x => x.Initializer).Where(i => i != null))
            {
                if (Utils.GetImpurities(var, semanticModel, knownSymbols, recursiveState).Any())
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 8
0
        public static bool AnyImpureFieldInitializer(
            TypeDeclarationSyntax typeDeclaration,
            SemanticModel semanticModel,
            KnownSymbols knownSymbols,
            RecursiveState recursiveState,
            InstanceStaticCombination instanceStaticCombination)
        {
            var fields =
                typeDeclaration.Members
                .OfType <FieldDeclarationSyntax>()
                .Where(instanceStaticCombination.Matches)
                .ToArray();

            foreach (var var in fields.SelectMany(x => x.Declaration.Variables))
            {
                if (Utils.GetImpurities(var, semanticModel, knownSymbols, recursiveState).Any())
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 9
0
        public static IEnumerable <ExpressionSyntax> GetNonNewObjectReturnsForPropertyGet(
            PropertyDeclarationSyntax propertyDeclaration,
            SemanticModel semanticModel,
            KnownSymbols knownSymbols,
            RecursiveState recursiveState1)
        {
            var propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration);

            if (propertySymbol.GetMethod == null)
            {
                yield break;
            }

            if (!propertySymbol.ReturnsByRef && IsCompleteValueType(propertySymbol.Type))
            {
                yield break;
            }

            List <ExpressionSyntax> returnExpressions;

            if (propertyDeclaration.AccessorList != null)
            {
                var getAccessor =
                    propertyDeclaration.AccessorList.Accessors.FirstOrNoValue(x =>
                                                                              x.Keyword.Kind() == SyntaxKind.GetKeyword);

                if (getAccessor.HasNoValue)
                {
                    yield break;
                }

                var getAccessorValue = getAccessor.GetValue();

                returnExpressions =
                    getAccessorValue.ExpressionBody != null
                        ? new List <ExpressionSyntax>()
                {
                    getAccessorValue.ExpressionBody.Expression
                }
                        : getAccessor.GetValue()
                .DescendantNodes()
                .OfType <ReturnStatementSyntax>()
                .Select(x => x.Expression)
                .ToList();
            }
            else if (propertyDeclaration.ExpressionBody != null)
            {
                returnExpressions = new List <ExpressionSyntax>()
                {
                    propertyDeclaration.ExpressionBody.Expression
                };
            }
            else
            {
                yield break;
            }

            foreach (var expression in returnExpressions)
            {
                if (!Utils.IsNewlyCreatedObject(semanticModel, expression, knownSymbols, RecursiveIsNewlyCreatedObjectState.Empty(), recursiveState1))
                {
                    yield return(expression);
                }
            }
        }
Exemplo n.º 10
0
 public static bool ReturnsNewObject(BaseMethodDeclarationSyntax methodDeclaration,
                                     SemanticModel semanticModel,
                                     KnownSymbols knownSymbols, RecursiveState recursiveState1)
 {
     return(!GetNonNewObjectReturnsForMethod(methodDeclaration, semanticModel, knownSymbols, recursiveState1).Any());
 }
Exemplo n.º 11
0
        public static List <ExpressionSyntax> GetValuesPossiblyInjectedInto(SemanticModel semanticModel,
                                                                            ILocalSymbol variable,
                                                                            SyntaxNode containingBlockNode, KnownSymbols knownSymbols, RecursiveState recursiveState)
        {
            var usages = containingBlockNode
                         .DescendantNodes()
                         .OfType <IdentifierNameSyntax>()
                         .Where(x => x.Identifier.Text == variable.Name)
                         .Where(x => semanticModel.GetSymbolInfo(x).Symbol?.Equals(variable) ?? false)
                         .Select(x => x.Parent)
                         .ToList();

            List <ExpressionSyntax> result = new List <ExpressionSyntax>();

            void HandleMemberAccess(MemberAccessExpressionSyntax usage)
            {
                if (usage.Parent is AssignmentExpressionSyntax assignment)
                {
                    result.Add(assignment.Right);
                }
                else if (usage.Parent is InvocationExpressionSyntax invocation)
                {
                    if (semanticModel.GetSymbolInfo(invocation.Expression).Symbol is IMethodSymbol invokedMethod)
                    {
                        var purityType = ImpuritiesFinder.GetMethodPurityType(semanticModel, knownSymbols,
                                                                              invokedMethod, recursiveState);

                        if (purityType.HasValueAnd(x => x.Equals(PurityType.PureExceptLocally)))
                        {
                            result.AddRange(invocation.ArgumentList.Arguments.Select(x => x.Expression));
                        }
                    }
                }
                else if (usage.Parent is MemberAccessExpressionSyntax memberAccess)
                {
                    HandleMemberAccess(memberAccess);
                }
            }

            foreach (var usage in usages)
            {
                if (usage is MemberAccessExpressionSyntax memberAccess)
                {
                    HandleMemberAccess(memberAccess);
                }
                else if (usage is ElementAccessExpressionSyntax elementAccess)
                {
                    if (elementAccess.Parent is AssignmentExpressionSyntax assignment)
                    {
                        result.Add(assignment.Right);
                    }
                }
            }

            return(result);
        }
Exemplo n.º 12
0
        public static bool IsNewlyCreatedObject(SemanticModel semanticModel,
                                                SyntaxNode expression,
                                                KnownSymbols knownSymbols,
                                                RecursiveIsNewlyCreatedObjectState recursiveState, RecursiveState recursiveState1)
        {
            if (expression is LiteralExpressionSyntax)
            {
                return(true);
            }

            if (expression is TupleExpressionSyntax tuple)
            {
                return(tuple.Arguments
                       .Select(x => x.Expression)
                       .All(x => IsNewlyCreatedObject(semanticModel, x, knownSymbols, recursiveState, recursiveState1)));
            }


            if (expression is ObjectCreationExpressionSyntax objectCreationExpression)
            {
                if (objectCreationExpression
                    .ArgumentList != null)
                {
                    if (objectCreationExpression
                        .ArgumentList
                        .Arguments.Any(arg =>
                                       !IsNewlyCreatedObject(semanticModel, arg.Expression, knownSymbols, recursiveState, recursiveState1)))
                    {
                        return(false);
                    }
                }


                if (objectCreationExpression.Initializer != null)
                {
                    if (objectCreationExpression
                        .Initializer
                        .Expressions
                        .OfType <AssignmentExpressionSyntax>()
                        .Any(x =>
                             !IsNewlyCreatedObject(semanticModel, x.Right, knownSymbols, recursiveState, recursiveState1)))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            if (expression is ArrayCreationExpressionSyntax arrayCreationExpression)
            {
                if (arrayCreationExpression.Initializer != null)
                {
                    if (arrayCreationExpression
                        .Initializer
                        .Expressions
                        .Any(x =>
                             !IsNewlyCreatedObject(semanticModel, x, knownSymbols, recursiveState, recursiveState1)))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            if (expression is ImplicitArrayCreationExpressionSyntax arrayCreationExpression1)
            {
                if (arrayCreationExpression1.Initializer != null)
                {
                    if (arrayCreationExpression1
                        .Initializer
                        .Expressions
                        .Any(x =>
                             !IsNewlyCreatedObject(semanticModel, x, knownSymbols, recursiveState, recursiveState1)))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            if (expression is InitializerExpressionSyntax initSyntax &&
                initSyntax.Kind() == SyntaxKind.ArrayInitializerExpression)
            {
                if (initSyntax
                    .Expressions
                    .Any(x =>
                         !IsNewlyCreatedObject(semanticModel, x, knownSymbols, recursiveState, recursiveState1)))
                {
                    return(false);
                }
                return(true);
            }

            if (expression is InvocationExpressionSyntax invocationExpression)
            {
                if (semanticModel.GetSymbolInfo(invocationExpression.Expression).Symbol is IMethodSymbol invokedMethod)
                {
                    if (MethodReturnsNewObject(semanticModel, knownSymbols, recursiveState1, invokedMethod))
                    {
                        return(true);
                    }
                }
            }

            if (expression is MemberAccessExpressionSyntax memberAccessExpression)
            {
                if (semanticModel.GetSymbolInfo(memberAccessExpression.Name).Symbol is IPropertySymbol propertySymbol && !GetUsage(memberAccessExpression.Name).IsWrite())
                {
                    if (MethodReturnsNewObject(semanticModel, knownSymbols, recursiveState1, propertySymbol.GetMethod))
                    {
                        return(true);
                    }
                }
            }

            if (expression is IdentifierNameSyntax identifier)
            {
                var identifierSymbol = semanticModel.GetSymbolInfo(identifier).Symbol;

                if (identifierSymbol is ILocalSymbol local)
                {
                    if (!local.IsRef && IsCompleteValueType(local.Type))
                    {
                        return(true);
                    }

                    if (recursiveState.VariablesUnderTest.Contains(local))
                    {
                        return(true);
                    }

                    var methodBody =
                        GetBodyOfMethodThatContainsExpression(expression);

                    if (methodBody.HasNoValue)
                    {
                        return(false);
                    }

                    var valuesInjectedIntoObject =
                        GetValuesPossiblyInjectedInto(semanticModel, local, methodBody.GetValue(), knownSymbols, recursiveState1);

                    if (!valuesInjectedIntoObject.All(x =>
                    {
                        var typeSymbol = semanticModel.GetTypeInfo(x).Type;

                        if (typeSymbol != null && IsImmutablePureData(typeSymbol))
                        {
                            return(true);
                        }

                        return(IsNewlyCreatedObject(semanticModel, x, knownSymbols, recursiveState.Add(local),
                                                    recursiveState1));
                    }))
                    {
                        return(false);
                    }

                    return(FindValuesAssignedToVariable(semanticModel, local, methodBody.GetValue()).All(x =>
                                                                                                         IsNewlyCreatedObject(semanticModel, x, knownSymbols, recursiveState.Add(local), recursiveState1)));
                }
            }

            if (semanticModel.GetTypeInfo(expression).Type is ITypeSymbol type)
            {
                if (IsCompleteValueType(type))
                {
                    return(true);
                }
            }

            return(false);
        }