Example #1
0
        /// <summary>Called once at compilation start to register actions in the compilation context.</summary>
        /// <param name="context">The analysis context.</param>
        internal void RegisterOperationAction(CompilationStartAnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
            {
                IArrayCreationExpression arrayCreation = (IArrayCreationExpression)operationContext.Operation;

                // ToDo: Need to suppress analysis of array creation expressions within attribute applications.

                // Detect array creation expression that have rank 1 and size 0. Such expressions
                // can be replaced with Array.Empty<T>(), provided that the element type can be a generic type argument.

                if (arrayCreation.DimensionSizes.Length == 1
                    //// Pointer types can't be generic type arguments.
                    && arrayCreation.ElementType.TypeKind != TypeKind.Pointer)
                {
                    Optional <object> arrayLength = arrayCreation.DimensionSizes[0].ConstantValue;
                    if (arrayLength.HasValue &&
                        arrayLength.Value is int &&
                        (int)arrayLength.Value == 0)
                    {
                        Report(operationContext, arrayCreation.Syntax);
                    }
                }
            },
                OperationKind.ArrayCreationExpression);
        }
        private void AnalyzeOperation(OperationAnalysisContext context)
        {
            IArrayCreationExpression arrayCreationExpression = context.Operation as IArrayCreationExpression;

            // We can't replace array allocations in attributes, as they're persisted to metadata
            // TODO: Once we have operation walkers, we can replace this syntactic check with an operation-based check.
            if (arrayCreationExpression.Syntax.Ancestors().Any(IsAttributeSyntax))
            {
                return;
            }

            if (arrayCreationExpression.DimensionSizes.Length == 1)
            {
                IOperation dimensionSize = arrayCreationExpression.DimensionSizes[0];

                if (dimensionSize.HasConstantValue(0))
                {
                    // Workaround for https://github.com/dotnet/roslyn/issues/10214
                    // Bail out for compiler generated param array creation.
                    if (IsCompilerGeneratedParamsArray(arrayCreationExpression, context))
                    {
                        return;
                    }

                    // pointers can't be used as generic arguments
                    if (arrayCreationExpression.ElementType.TypeKind != TypeKind.Pointer)
                    {
                        context.ReportDiagnostic(context.Operation.Syntax.CreateDiagnostic(UseArrayEmptyDescriptor));
                    }
                }
            }
        }
Example #3
0
        private static IArrayCreationExpression CreateArrayCreationExpression(IType elementType, CSharpElementFactory factory)
        {
            IArrayCreationExpression expression = (IArrayCreationExpression)factory.CreateExpression("new[]{}", new object[0]);
            IArrayType arrayType = TypeFactory.CreateArrayType(elementType, 1, null);

            return(factory.CreateArrayCreationExpression(arrayType, expression.ArrayInitializer));
        }
        private static bool IsCompilerGeneratedParamsArray(IArrayCreationExpression arrayCreationExpression, OperationAnalysisContext context)
        {
            var model = context.Compilation.GetSemanticModel(arrayCreationExpression.Syntax.SyntaxTree);

            // Compiler generated array creation seems to just use the syntax from the parent.
            var parent = model.GetOperationInternal(arrayCreationExpression.Syntax, context.CancellationToken) as IInvocationExpression;

            if (parent?.TargetMethod == null || parent.TargetMethod.Parameters.Length == 0)
            {
                return(false);
            }

            if (!parent.TargetMethod.Parameters.Last().IsParams)
            {
                return(false);
            }

            // At this point the array creation is known to be compiler synthesized as part of a call
            // to a method with a params parameter, and so it is probably sound to return true at this point.
            // As a sanity check, verify that the last argument to the call is equivalent to the array creation.
            // (Comparing for object identity does not work because the semantic model can return a fresh operation tree.)
            var lastArgument = parent.ArgumentsInParameterOrder.LastOrDefault();

            return(lastArgument != null && lastArgument.Value.Syntax == arrayCreationExpression.Syntax && AreEquivalentZeroLengthArrayCreations(arrayCreationExpression, lastArgument.Value as IArrayCreationExpression));
        }
        private void AnalyzeOperation(OperationAnalysisContext context)
        {
            IArrayCreationExpression arrayCreationExpression = context.Operation as IArrayCreationExpression;

            // We can't replace array allocations in attributes, as they're persisted to metadata
            // TODO: Once we have operation walkers, we can replace this syntactic check with an operation-based check.
            if (arrayCreationExpression.Syntax.Ancestors().Any(IsAttributeSyntax))
            {
                return;
            }

            if (arrayCreationExpression.DimensionSizes.Length == 1)
            {
                IOperation dimensionSize = arrayCreationExpression.DimensionSizes[0];

                if (dimensionSize.ConstantValue.HasValue && (int)dimensionSize.ConstantValue.Value == 0)
                {
                    // pointers can't be used as generic arguments
                    if (arrayCreationExpression.ElementType.TypeKind != TypeKind.Pointer)
                    {
                        context.ReportDiagnostic(context.Operation.Syntax.CreateDiagnostic(UseArrayEmptyDescriptor));
                    }
                }
            }
        }
        public override void VisitArrayCreationExpression(IArrayCreationExpression operation)
        {
            LogString(nameof(IArrayCreationExpression));
            LogString($" (Dimension sizes: {operation.DimensionSizes.Length}, Element Type: {operation.ElementType?.ToTestDisplayString()})");
            LogCommonPropertiesAndNewLine(operation);

            base.VisitArrayCreationExpression(operation);
        }
Example #7
0
        /// <summary>
        /// Swap to built in type alias.
        /// </summary>
        /// <param name="node">
        /// The node to process.
        /// </param>
        public static void SwapToBuiltInTypeAlias(ITreeNode node)
        {
            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                ITypeArgumentList typeArgumentListNode = currentNode as ITypeArgumentList;
                if (typeArgumentListNode != null)
                {
                    SwapGenericDeclarationToBuiltInType(typeArgumentListNode);
                }
                else
                {
                    IMethodDeclaration methodDeclarationNode = currentNode as IMethodDeclaration;
                    if (methodDeclarationNode != null)
                    {
                        SwapReturnTypeToBuiltInType(methodDeclarationNode);
                    }
                    else
                    {
                        IVariableDeclaration variableDeclaration = currentNode as IVariableDeclaration;
                        if (variableDeclaration != null)
                        {
                            SwapVariableDeclarationToBuiltInType(variableDeclaration);
                        }
                        else
                        {
                            IObjectCreationExpression creationExpressionNode = currentNode as IObjectCreationExpression;
                            if (creationExpressionNode != null)
                            {
                                //// No need to call this now and its messing up nested {}
                                //// SwapObjectCreationToBuiltInType(creationExpressionNode);
                            }
                            else
                            {
                                IArrayCreationExpression arrayCreationNode = currentNode as IArrayCreationExpression;
                                if (arrayCreationNode != null)
                                {
                                    SwapArrayCreationToBuiltInType(arrayCreationNode);
                                }
                                else
                                {
                                    IReferenceExpression referenceExpressionNode = currentNode as IReferenceExpression;
                                    if (referenceExpressionNode != null)
                                    {
                                        SwapReferenceExpressionToBuiltInType(referenceExpressionNode);
                                    }
                                }
                            }
                        }
                    }
                }

                if (currentNode != null && currentNode.FirstChild != null)
                {
                    SwapToBuiltInTypeAlias(currentNode.FirstChild);
                }
            }
        }
        public override void VisitArrayCreationExpression(IArrayCreationExpression operation)
        {
            LogString(nameof(IArrayCreationExpression));
            LogString($" (Element Type: {operation.ElementType?.ToTestDisplayString()})");
            LogCommonPropertiesAndNewLine(operation);

            VisitArray(operation.DimensionSizes, "Dimension Sizes", logElementCount: true);
            Visit(operation.Initializer, "Initializer");
        }
Example #9
0
 public InefficientMultidimensionalArrayUsageQuickFix(InefficientMultidimensionalArrayUsageWarning warning)
 {
     myWarning                 = warning;
     myVariableDeclaration     = warning.VariableDeclaration;
     myTreeNodePointers        = warning.Usages;
     myArrayCreationExpression = warning.ArrayCreationExpression;
     myType = (myVariableDeclaration.Type as IArrayType).NotNull("type != null");
     myMultipleDeclaration = warning.MultiplyDeclaration;
 }
Example #10
0
        private static void CheckArrayCreation(
            [NotNull] IArrayCreationExpression arrayCreation, [NotNull] IHighlightingConsumer consumer)
        {
            if (arrayCreation.GetContainingNode <IAttribute>() == null)
            {
                var newKeyword = arrayCreation.NewKeyword.NotNull();

                consumer.AddHighlighting(
                    new ObjectAllocationHighlighting(newKeyword, "array creation"),
                    newKeyword.GetDocumentRange());
            }
        }
        private static void CheckArrayCreation([NotNull] IArrayCreationExpression arrayCreation, [NotNull] IHighlightingConsumer consumer)
        {
            if (arrayCreation.IsInTheContextWhereAllocationsAreNotImportant())
            {
                return;
            }

            var newKeyword = arrayCreation.NewKeyword.NotNull();

            consumer.AddHighlighting(
                new ObjectAllocationEvidentHighlighting(newKeyword, "array creation"),
                newKeyword.GetDocumentRange());
        }
        private static bool IsCompilerGeneratedParamsArray(IArrayCreationExpression arrayCreationExpression, OperationAnalysisContext context)
        {
            var model = context.Compilation.GetSemanticModel(arrayCreationExpression.Syntax.SyntaxTree);

            // Compiler generated array creation seems to just use the syntax from the parent.
            var parent = model.GetOperationInternal(arrayCreationExpression.Syntax, context.CancellationToken) as IHasArgumentsExpression;

            if (parent == null)
            {
                return(false);
            }

            ISymbol targetSymbol;

            if (parent is IInvocationExpression invocation)
            {
                targetSymbol = invocation.TargetMethod;
            }
            else
            {
                if (parent is IObjectCreationExpression objectCreation)
                {
                    targetSymbol = objectCreation.Constructor;
                }
                else
                {
                    targetSymbol = (parent as IIndexedPropertyReferenceExpression)?.Property;
                }
            }

            if (targetSymbol == null)
            {
                return(false);
            }

            var parameters = targetSymbol.GetParameters();

            if (parameters.Length == 0 || !parameters[parameters.Length - 1].IsParams)
            {
                return(false);
            }

            // At this point the array creation is known to be compiler synthesized as part of a call
            // to a method with a params parameter, and so it is probably sound to return true at this point.
            // As a sanity check, verify that the last argument to the call is equivalent to the array creation.
            // (Comparing for object identity does not work because the semantic model can return a fresh operation tree.)
            var lastArgument = parent.ArgumentsInEvaluationOrder.LastOrDefault();

            return(lastArgument != null && lastArgument.Value.Syntax == arrayCreationExpression.Syntax && AreEquivalentZeroLengthArrayCreations(arrayCreationExpression, lastArgument.Value as IArrayCreationExpression));
        }
        /// <summary>
        /// The execute transaction inner.
        /// </summary>
        /// <param name="solution">
        /// The solution.
        /// </param>
        /// <param name="textControl">
        /// The text control.
        /// </param>
        public override void ExecuteTransactionInner(ISolution solution, ITextControl textControl)
        {
            IList <ITokenNode> tokensForLine = Utils.GetTokensForLineFromTextControl(solution, textControl);

            foreach (ITokenNode tokenNode in tokensForLine)
            {
                ITypeArgumentList typeArgumentListNode = tokenNode.GetContainingNode <ITypeArgumentList>(true);

                if (typeArgumentListNode != null)
                {
                    ReadabilityRules.SwapToBuiltInTypeAlias(typeArgumentListNode);
                }

                IObjectCreationExpression objectCreationExpressionNode = tokenNode.GetContainingNode <IObjectCreationExpression>(true);

                if (objectCreationExpressionNode != null)
                {
                    ReadabilityRules.SwapToBuiltInTypeAlias(objectCreationExpressionNode);
                }

                IArrayCreationExpression arrayCreationExpressionNode = tokenNode.GetContainingNode <IArrayCreationExpression>(true);

                if (arrayCreationExpressionNode != null)
                {
                    ReadabilityRules.SwapToBuiltInTypeAlias(arrayCreationExpressionNode);
                }

                IMethodDeclaration methodDeclaration = tokenNode.GetContainingNode <IMethodDeclaration>(true);

                if (methodDeclaration != null)
                {
                    ReadabilityRules.SwapToBuiltInTypeAlias(methodDeclaration);
                }

                IVariableDeclaration variableDeclaration = tokenNode.GetContainingNode <IVariableDeclaration>(true);

                if (variableDeclaration != null)
                {
                    ReadabilityRules.SwapToBuiltInTypeAlias(variableDeclaration);
                }

                IMultipleDeclaration multipleDeclarationNode = tokenNode.GetContainingNode <IMultipleDeclaration>(true);

                if (multipleDeclarationNode != null)
                {
                    ReadabilityRules.SwapToBuiltInTypeAlias(multipleDeclarationNode);
                }
            }
        }
Example #14
0
        /// <summary>
        /// Swap array creation to built in type.
        /// </summary>
        /// <param name="arrayCreationExpression">
        /// The array creation expression.
        /// </param>
        private static void SwapArrayCreationToBuiltInType(IArrayCreationExpression arrayCreationExpression)
        {
            if (!arrayCreationExpression.IsImplicitlyTypedArray)
            {
                using (WriteLockCookie.Create(true))
                {
                    bool fileIsCSharp30 = arrayCreationExpression.IsCSharp3Supported();

                    // If the array creation type is the same type as the initializer (and we are CSharp 3.0 or greater) remove it completely
                    IArrayType arrayType = arrayCreationExpression.Type() as IArrayType;
                    if ((arrayType != null) && arrayCreationExpression.ArrayInitializer != null && fileIsCSharp30 &&
                        arrayType.ElementType.Equals(arrayCreationExpression.ArrayInitializer.GetElementType(true)))
                    {
                        IList <IRankSpecifier> dims = arrayCreationExpression.Dims;
                        arrayCreationExpression.SetArrayType(null);
                        for (int i = 0; i < (dims.Count - 1); i++)
                        {
                            using (WriteLockCookie.Create(true))
                            {
                                ModificationUtil.DeleteChild(dims[i]);
                            }
                        }

                        foreach (ICSharpExpression size in arrayCreationExpression.Sizes)
                        {
                            if (size != null)
                            {
                                using (WriteLockCookie.Create(true))
                                {
                                    ModificationUtil.DeleteChild(size);
                                }
                            }
                        }
                    }
                    else
                    {
                        using (WriteLockCookie.Create(true))
                        {
                            arrayCreationExpression.SetArrayType(arrayType);
                        }
                    }
                }
            }
        }
Example #15
0
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
            {
                IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation;
                long priorArgumentValue          = long.MinValue;
                foreach (IArgument argument in invocation.ArgumentsInParameterOrder)
                {
                    TestAscendingArgument(operationContext, argument.Value, ref priorArgumentValue);

                    if (argument.Kind == ArgumentKind.ParamArray)
                    {
                        IArrayCreationExpression arrayArgument = argument.Value as IArrayCreationExpression;
                        if (arrayArgument != null && arrayArgument.ElementValues.ArrayClass == ArrayInitializerKind.Dimension)
                        {
                            IDimensionArrayInitializer dimension = arrayArgument.ElementValues as IDimensionArrayInitializer;
                            if (dimension != null)
                            {
                                if (dimension.ElementValues.Length > 10)
                                {
                                    Report(operationContext, invocation.Syntax, BigParamarrayArgumentsDescriptor);
                                }

                                foreach (IArrayInitializer dimensionValues in dimension.ElementValues)
                                {
                                    if (dimensionValues.ArrayClass == ArrayInitializerKind.Expression)
                                    {
                                        IExpressionArrayInitializer expressionInitializer = dimensionValues as IExpressionArrayInitializer;
                                        if (expressionInitializer != null)
                                        {
                                            TestAscendingArgument(operationContext, expressionInitializer.ElementValue, ref priorArgumentValue);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
                OperationKind.InvocationExpression);
        }
Example #16
0
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
            {
                IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation;

                foreach (IArgument argument in invocation.ArgumentsInSourceOrder)
                {
                    if (argument.Parameter.IsParams)
                    {
                        IArrayCreationExpression arrayValue = argument.Value as IArrayCreationExpression;
                        if (arrayValue != null)
                        {
                            Optional <object> dimensionSize = arrayValue.DimensionSizes[0].ConstantValue;
                            if (dimensionSize.HasValue && IntegralValue(dimensionSize.Value) > 3)
                            {
                                operationContext.ReportDiagnostic(Diagnostic.Create(LongParamsDescriptor, argument.Value.Syntax.GetLocation()));
                            }
                        }
                    }
                }

                foreach (IArgument argument in invocation.ArgumentsInParameterOrder)
                {
                    if (argument.Parameter.IsParams)
                    {
                        IArrayCreationExpression arrayValue = argument.Value as IArrayCreationExpression;
                        if (arrayValue != null)
                        {
                            Optional <object> dimensionSize = arrayValue.DimensionSizes[0].ConstantValue;
                            if (dimensionSize.HasValue && IntegralValue(dimensionSize.Value) > 3)
                            {
                                operationContext.ReportDiagnostic(Diagnostic.Create(LongParamsDescriptor, argument.Value.Syntax.GetLocation()));
                            }
                        }
                    }
                }
            },
                OperationKind.InvocationExpression);
        }
        private static bool AreEquivalentZeroLengthArrayCreations(IArrayCreationExpression first, IArrayCreationExpression second)
        {
            if (first == null || second == null)
            {
                return false;
            }

            ImmutableArray<IOperation> sizes = first.DimensionSizes;
            if (sizes.Length != 1 || !sizes[0].HasConstantValue(0))
            {
                return false;
            }

            sizes = second.DimensionSizes;
            if (sizes.Length != 1 || !sizes[0].HasConstantValue(0))
            {
                return false;
            }

            return first.Type.Equals(second.Type);
        }
        private static bool AreEquivalentZeroLengthArrayCreations(IArrayCreationExpression first, IArrayCreationExpression second)
        {
            if (first == null || second == null)
            {
                return(false);
            }

            ImmutableArray <IOperation> sizes = first.DimensionSizes;

            if (sizes.Length != 1 || !sizes[0].HasConstantValue(0))
            {
                return(false);
            }

            sizes = second.DimensionSizes;
            if (sizes.Length != 1 || !sizes[0].HasConstantValue(0))
            {
                return(false);
            }

            return(first.Type.Equals(second.Type));
        }
        private static bool IsCompilerGeneratedParamsArray(IArrayCreationExpression arrayCreationExpression, OperationAnalysisContext context)
        {
            var model = context.Compilation.GetSemanticModel(arrayCreationExpression.Syntax.SyntaxTree);

            // Compiler generated array creation seems to just use the syntax from the parent.
            var parent = model.GetOperation(arrayCreationExpression.Syntax, context.CancellationToken) as IInvocationExpression;

            if (parent == null || parent.TargetMethod == null || parent.TargetMethod.Parameters.Length == 0)
            {
                return(false);
            }

            if (!parent.TargetMethod.Parameters.Last().IsParams)
            {
                return(false);
            }

            var lastArgument = parent.ArgumentsInParameterOrder.LastOrDefault();

            return(lastArgument.Syntax == parent.Syntax &&
                   lastArgument != null &&
                   lastArgument.ArgumentKind == ArgumentKind.ParamArray);
        }
        private void AnalyzeOperation(OperationAnalysisContext context, Func <SyntaxNode, bool> isAttributeSytnax)
        {
            IArrayCreationExpression arrayCreationExpression = (IArrayCreationExpression)context.Operation;

            // We can't replace array allocations in attributes, as they're persisted to metadata
            // TODO: Once we have operation walkers, we can replace this syntactic check with an operation-based check.
            if (arrayCreationExpression.Syntax.Ancestors().Any(isAttributeSytnax))
            {
                return;
            }

            if (arrayCreationExpression.DimensionSizes.Length == 1)
            {
                IOperation dimensionSize = arrayCreationExpression.DimensionSizes[0];

                if (dimensionSize.HasConstantValue(0))
                {
                    // Workaround for https://github.com/dotnet/roslyn/issues/10214
                    // Bail out for compiler generated param array creation.
                    if (IsCompilerGeneratedParamsArray(arrayCreationExpression, context))
                    {
                        return;
                    }

                    // pointers can't be used as generic arguments
                    if (arrayCreationExpression.ElementType.TypeKind != TypeKind.Pointer)
                    {
                        var           arrayType   = context.Compilation.GetTypeByMetadataName(ArrayTypeName);
                        IMethodSymbol emptyMethod = (IMethodSymbol)arrayType.GetMembers(ArrayEmptyMethodName).First();
                        var           constructed = emptyMethod.Construct(arrayCreationExpression.ElementType);

                        string typeName = constructed.ToDisplayString(ReportFormat);
                        context.ReportDiagnostic(context.Operation.Syntax.CreateDiagnostic(UseArrayEmptyDescriptor, typeName));
                    }
                }
            }
        }
Example #21
0
 public virtual void VisitArrayCreationExpression(IArrayCreationExpression operation)
 {
     DefaultVisit(operation);
 }
        /// <summary>
        /// Swap array creation to built in type.
        /// </summary>
        /// <param name="arrayCreationExpression">
        /// The array creation expression.
        /// </param>
        private static void SwapArrayCreationToBuiltInType(IArrayCreationExpression arrayCreationExpression)
        {
            if (!arrayCreationExpression.IsImplicitlyTypedArray)
            {
                using (WriteLockCookie.Create(true))
                {
                    bool fileIsCSharp30 = arrayCreationExpression.IsCSharp3Supported();

                    // If the array creation type is the same type as the initializer (and we are CSharp 3.0 or greater) remove it completely
                    IArrayType arrayType = arrayCreationExpression.Type() as IArrayType;
                    if ((arrayType != null) && arrayCreationExpression.ArrayInitializer != null && fileIsCSharp30
                        && arrayType.ElementType.Equals(arrayCreationExpression.ArrayInitializer.GetElementType(true)))
                    {
                        TreeNodeCollection<IRankSpecifier> dims = arrayCreationExpression.Dims;
                        arrayCreationExpression.SetArrayType(null);
                        for (int i = 0; i < (dims.Count - 1); i++)
                        {
                            using (WriteLockCookie.Create(true))
                            {
                                ModificationUtil.DeleteChild(dims[i]);
                            }
                        }

                        foreach (ICSharpExpression size in arrayCreationExpression.Sizes)
                        {
                            if (size != null)
                            {
                                using (WriteLockCookie.Create(true))
                                {
                                    ModificationUtil.DeleteChild(size);
                                }
                            }
                        }
                    }
                    else
                    {
                        using (WriteLockCookie.Create(true))
                        {
                            arrayCreationExpression.SetArrayType(arrayType);
                        }
                    }
                }
            }
        }
Example #23
0
 public virtual void VisitArrayCreationExpression(IArrayCreationExpression operation)
 {
     DefaultVisit(operation);
 }
 public override void VisitArrayCreationExpression(IArrayCreationExpression operation)
 {
     base.VisitArrayCreationExpression(operation);
 }
Example #25
0
 public override void VisitArrayCreationExpression(IArrayCreationExpression operation)
 {
     var elementType = operation.ElementType;
     
     base.VisitArrayCreationExpression(operation);
 }
Example #26
0
 public override void VisitArrayCreationExpression(IArrayCreationExpression operation)
 {
     VisitArray(operation.DimensionSizes);
     Visit(operation.Initializer);
 }
Example #27
0
        public override void VisitArrayCreationExpression(IArrayCreationExpression operation)
        {
            var elementType = operation.ElementType;

            base.VisitArrayCreationExpression(operation);
        }
Example #28
0
 public override IOperation VisitArrayCreationExpression(IArrayCreationExpression operation, object argument)
 {
     return(new ArrayCreationExpression(VisitArray(operation.DimensionSizes), Visit(operation.Initializer), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit));
 }
 /// <inheritdoc />
 public override IOperation VisitArrayCreationExpression(IArrayCreationExpression operation, object argument)
 {
     return(base.VisitArrayCreationExpression(operation, argument));
 }
 /// <inheritdoc />
 public override Expression VisitArrayCreationExpression(IArrayCreationExpression operation, LocalBinder argument)
 {
     return(base.VisitArrayCreationExpression(operation, argument));
 }
        private static bool IsCompilerGeneratedParamsArray(IArrayCreationExpression arrayCreationExpression, OperationAnalysisContext context)
        {
            var model = context.Compilation.GetSemanticModel(arrayCreationExpression.Syntax.SyntaxTree);

            // Compiler generated array creation seems to just use the syntax from the parent.
            var parent = model.GetOperation(arrayCreationExpression.Syntax, context.CancellationToken) as IInvocationExpression;
            if (parent?.TargetMethod == null || parent.TargetMethod.Parameters.Length == 0)
            {
                return false;
            }

            if (!parent.TargetMethod.Parameters.Last().IsParams)
            {
                return false;
            }

            // At this point the array creation is known to be compiler synthesized as part of a call
            // to a method with a params parameter, and so it is probably sound to return true at this point.
            // As a sanity check, verify that the last argument to the call is equivalent to the array creation.
            // (Comparing for object identity does not work because the semantic model can return a fresh operation tree.)
            var lastArgument = parent.ArgumentsInParameterOrder.LastOrDefault();
            return lastArgument != null && lastArgument.Value.Syntax == arrayCreationExpression.Syntax && AreEquivalentZeroLengthArrayCreations(arrayCreationExpression, lastArgument.Value as IArrayCreationExpression);
        }
 public static IArrayCreationExpression Update(this IArrayCreationExpression self, ImmutableArray <IOperation> @bounds, IOperation @initializerOpt, ITypeSymbol @type) => self;
        private static bool IsCompilerGeneratedParamsArray(IArrayCreationExpression arrayCreationExpression, OperationAnalysisContext context)
        {
            var model = context.Compilation.GetSemanticModel(arrayCreationExpression.Syntax.SyntaxTree);

            // Compiler generated array creation seems to just use the syntax from the parent.
            var parent = model.GetOperation(arrayCreationExpression.Syntax, context.CancellationToken) as IInvocationExpression;
            if (parent == null || parent.TargetMethod == null || parent.TargetMethod.Parameters.Length == 0)
            {
                return false;
            }

            if (!parent.TargetMethod.Parameters.Last().IsParams)
            {
                return false;
            }

            var lastArgument = parent.ArgumentsInParameterOrder.LastOrDefault();
            return lastArgument.Syntax == parent.Syntax &&
                lastArgument != null &&
                lastArgument.ArgumentKind == ArgumentKind.ParamArray;
        }
        public static void CreateInefficientMultidimensionalArrayAccessWarning([CanBeNull] IDeclaredElement declaredElement,
                                                                               [NotNull] IVariableDeclaration variableDeclaration, [NotNull]  IDaemonProcess daemonProcess, [NotNull]  DaemonProcessKind kind,
                                                                               [NotNull] IHighlightingConsumer consumer, [NotNull] DocumentRange highlightingRange)
        {
            if (declaredElement == null)
            {
                return;
            }

            var type = variableDeclaration.Type as IArrayType;

            if (type == null)
            {
                return;
            }

            if (type.Rank == 1)
            {
                return;
            }

            IArrayCreationExpression arrayCreationExpression = null;
            IMultipleDeclaration     multipleDeclaration     = null;

            switch (variableDeclaration)
            {
            case IFieldDeclaration fieldDeclaration:
                // perfomance optimization
                if (fieldDeclaration.GetAccessRights() != AccessRights.PRIVATE)
                {
                    return;
                }

                arrayCreationExpression = (fieldDeclaration.Initial as IExpressionInitializer)?.Value as IArrayCreationExpression;
                multipleDeclaration     = MultipleFieldDeclarationNavigator.GetByDeclarator(fieldDeclaration);

                break;

            case ILocalVariableDeclaration localVariableDeclaration:
                var initial = localVariableDeclaration.Initial;
                arrayCreationExpression = (initial as IExpressionInitializer)?.Value as IArrayCreationExpression;

                if (initial != null && arrayCreationExpression == null)
                {
                    return;
                }

                multipleDeclaration =
                    MultipleLocalVariableDeclarationNavigator.GetByDeclarator(localVariableDeclaration);
                break;

            default:
                return;
            }

            var classDeclaration = variableDeclaration.GetContainingNode <IClassLikeDeclaration>();

            if (classDeclaration == null)
            {
                return;
            }

            var usages = FindArrayUsages(declaredElement, classDeclaration, daemonProcess, kind);

            foreach (var usage in usages)
            {
                if (ElementAccessExpressionNavigator.GetByOperand(usage as ICSharpExpression) == null)
                {
                    return;
                }
            }

            if (arrayCreationExpression.ContainsErrorElement())
            {
                return;
            }

            consumer.AddHighlighting(new InefficientMultidimensionalArrayUsageWarning(usages.Select(t => t.CreateTreeElementPointer()).ToList(),
                                                                                      arrayCreationExpression, variableDeclaration, multipleDeclaration, highlightingRange));
        }