Example #1
0
            private static void ExpandInvocationOperation(
                IInvocationOperation invocationOperation,
                WellKnownSymbolsInfo wellKnownSymbolsInfo,
                Queue <IOperation> queue)
            {
                // Check the arguments of this invocation to see if this is a deferred executing method.
                // e.g.
                // var a = b.Concat(c);
                // When we looking at the creation of 'a', we want to find both 'b' and 'c'
                foreach (var argument in invocationOperation.Arguments)
                {
                    if (IsLinqChainInvocation(invocationOperation, argument, wellKnownSymbolsInfo, out _))
                    {
                        queue.Enqueue(argument.Value);
                    }
                }

                // Also check it's invocation instance if the extension method could be used in reduced form.
                // e.g.
                // Dim a = b.Concat(c)
                // We need enqueue the invocation instance (which is 'b') if the target method is a reduced extension method
                if (IsLinqChainInvocation(invocationOperation, wellKnownSymbolsInfo, out _))
                {
                    queue.Enqueue(invocationOperation.Instance);
                }
            }
Example #2
0
 private static void ExpandConversionOperation(
     IConversionOperation conversionOperation,
     WellKnownSymbolsInfo wellKnownSymbolsInfo,
     Queue <IOperation> queue)
 {
     if (IsValidImplicitConversion(conversionOperation, wellKnownSymbolsInfo))
     {
         queue.Enqueue(conversionOperation.Operand);
     }
 }
Example #3
0
            static (IOperation linqChainTailOperation, EnumerationCount enumerationCount) VisitLinqChainAndCoversionMethod(
                IOperation operation,
                EnumerationCount enumerationCount,
                WellKnownSymbolsInfo wellKnownSymbolsInfo)
            {
                if (IsValidImplicitConversion(operation.Parent, wellKnownSymbolsInfo))
                {
                    // Go to the implicit conversion if needed
                    // e.g.
                    // void Bar (IOrderedEnumerable<T> c)
                    // {
                    //      c.First();
                    // }
                    // here 'c' would be converted to IEnumerable<T>
                    return(VisitLinqChainAndCoversionMethod(operation.Parent, enumerationCount, wellKnownSymbolsInfo));
                }

                if (IsOperationIsArgumentOfLinqChainInvocation(operation.Parent, wellKnownSymbolsInfo, out var enumerateArgument))
                {
                    // This operation is used as an argument of a deferred execution method.
                    // Check if the invocation of the deferred execution method is used in another deferred execution method.
                    return(VisitLinqChainAndCoversionMethod(
                               operation.Parent.Parent,
                               enumerateArgument
                            ? InvocationSetHelpers.AddInvocationCount(enumerationCount, EnumerationCount.One)
                            : enumerationCount,
                               wellKnownSymbolsInfo));
                }

                if (IsInstanceOfLinqChainInvocation(operation, wellKnownSymbolsInfo, out var enumerateInstance))
                {
                    // If the extension method could be used as reduced method, also check its invocation instance.
                    // Like in VB,
                    // 'i.Select(Function(a) a)', 'i' is the invocation instance of 'Select'
                    return(VisitLinqChainAndCoversionMethod(
                               operation.Parent,
                               enumerateInstance
                            ? InvocationSetHelpers.AddInvocationCount(enumerationCount, EnumerationCount.One)
                            : enumerationCount,
                               wellKnownSymbolsInfo));
                }

                return(operation, enumerationCount);
            }
Example #4
0
            private EnumerationCount GetEnumerationCount(IOperation parameterOrLocalReferenceOperation, WellKnownSymbolsInfo wellKnownSymbolsInfo)
            {
                var(linqChainTailOperation, linqChainEnumerationCount) = SkipLinqChainAndConversionMethod(
                    parameterOrLocalReferenceOperation,
                    wellKnownSymbolsInfo);

                if (IsOperationEnumeratedByInvocation(linqChainTailOperation, wellKnownSymbolsInfo) ||
                    IsGetEnumeratorOfForEachLoopInvoked(linqChainTailOperation))
                {
                    return(InvocationSetHelpers.AddInvocationCount(linqChainEnumerationCount, EnumerationCount.One));
                }

                return(linqChainEnumerationCount);
            }
Example #5
0
 protected AvoidMultipleEnumerationsFlowStateDictionaryFlowOperationVisitor(
     GlobalFlowStateDictionaryAnalysisContext analysisContext,
     WellKnownSymbolsInfo wellKnownSymbolsInfo) : base(analysisContext)
 {
     _wellKnownSymbolsInfo = wellKnownSymbolsInfo;
 }
Example #6
0
 /// <summary>
 /// Skip the deferred method call and conversion operation in Linq methods call chain.
 /// Return the tail of the Linq chain operation, and possible enumerationCount by the Linq Chain Method.
 /// </summary>
 public static (IOperation linqChainTailOperation, EnumerationCount linqChainEnumerationCount) SkipLinqChainAndConversionMethod(
     IOperation operation,
     WellKnownSymbolsInfo wellKnownSymbolsInfo)
 {
     RoslynDebug.Assert(operation is IParameterReferenceOperation or ILocalReferenceOperation);
     return(VisitLinqChainAndCoversionMethod(operation, EnumerationCount.Zero, wellKnownSymbolsInfo));