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); }
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); }