Beispiel #1
0
        //--- Class Methods ---
        private static void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
        {
            var semanticModel = context.SemanticModel;
            var node          = context.Node;

            // check to see if the invocation target is in the current assembly
            var invocationInfo = context.SemanticModel.GetSymbolInfo(node);

            if (!invocationInfo.Symbol?.ContainingAssembly.Name.Equals(context.SemanticModel.Compilation.AssemblyName) ?? true)
            {
                return;
            }
            foreach (var argument in from invocationNode in node.DescendantNodes()

                     // find all arguments
                     where invocationNode.Kind() == SyntaxKind.Argument
                     let argumentDescendantNode = invocationNode.DescendantNodes().FirstOrDefault()
                                                  where argumentDescendantNode != null

                                                  // do not evaluate out parameters on method invocations
                                                  where argumentDescendantNode.Parent.GetFirstToken().Kind() != SyntaxKind.OutKeyword

                                                  // check if the argument type is IEnumerable, and if it is abstract
                                                  let typeInfo = semanticModel.GetTypeInfo(argumentDescendantNode)

                                                                 // TODO (2016-02-25, steveb): concrete classes that implement IEnumerable<> may be lazy; this check doesn't account for that
                                                                 where MaterializedCollectionsUtils.IsAbstractCollectionType(typeInfo)

                                                                 where MaterializedCollectionsUtils.ShouldReportOnCollectionNode(semanticModel, argumentDescendantNode)
                                                                 select argumentDescendantNode
                     )
            {
                ReportDiagnostic(context, argument.GetLocation());
            }
        }
        //--- Class Methods ---
        private static async Task <Document> MakeArray(Document document, SyntaxToken typeDecl, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

            // check to see if this is an argument to a method call
            SyntaxNode node = null;

            if (typeDecl.Parent.Ancestors().Any(x => x.Kind() == SyntaxKind.Argument))
            {
                node = typeDecl.Parent.Ancestors()
                       .Where(x => x.Kind() == SyntaxKind.Argument)
                       .Select(x => x.DescendantNodes().FirstOrDefault())
                       .FirstOrDefault();

                // check to see if we are dealing with a return statement
            }
            else if (typeDecl.Parent.Ancestors().Any(x => x.Kind() == SyntaxKind.ReturnStatement))
            {
                node = typeDecl.Parent.Ancestors().Where(x => x.Kind() == SyntaxKind.ReturnStatement).Select(x => x.DescendantNodes().FirstOrDefault()).FirstOrDefault();
            }
            if (node == null)
            {
                // we did not recognize this node, do nothing
                return(document);
            }

            var typeInfo = semanticModel.GetTypeInfo(node);
            var tree     = await document.GetSyntaxTreeAsync(cancellationToken);

            var root = (CompilationUnitSyntax)tree.GetRoot(cancellationToken);

            if (MaterializedCollectionsUtils.IsCollection(typeInfo.ConvertedType) && typeInfo.Type.IsAbstract)
            {
                // generate a .ToArray() call around the argument
                var newNode = SyntaxFactory.InvocationExpression(
                    SyntaxFactory.MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        (ExpressionSyntax)node,
                        SyntaxFactory.IdentifierName(@"ToArray")
                        ),
                    SyntaxFactory.ArgumentList()
                    );
                var newRoot = root.ReplaceNode(node, newNode);
                return(document.WithSyntaxRoot(newRoot));
            }
            return(document);
        }
Beispiel #3
0
        private static void AnalyzeReturnStatement(SyntaxNodeAnalysisContext context)
        {
            var semanticModel = context.SemanticModel;
            var node          = context.Node.DescendantNodes().FirstOrDefault();

            if (node == null)
            {
                return;
            }
            var typeInfo = semanticModel.GetTypeInfo(node);

            if (MaterializedCollectionsUtils.IsAbstractCollectionType(typeInfo))
            {
                if (MaterializedCollectionsUtils.ShouldReportOnCollectionNode(semanticModel, node))
                {
                    ReportDiagnostic(context, node.GetLocation());
                }
            }
        }