private ProgramState ProcessInvocation(ProgramState programState, InvocationExpressionSyntax invocation) { // Argument of the nameof expression is not pushed on stack so we need to exit the checks if (invocation.IsNameof(semanticModel)) { return(programState); } // Remove collection constraint from all arguments passed to an invocation var newProgramState = RemoveCollectionConstraintsFromArguments(invocation.ArgumentList, programState); var memberAccess = invocation.Expression as MemberAccessExpressionSyntax; if (memberAccess == null) { return(newProgramState); } var collectionSymbol = semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol; var collectionType = GetCollectionType(collectionSymbol); // When invoking a collection method ... if (collectionType.IsAny(TrackedCollectionTypes)) { var methodSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; if (IsIgnoredMethod(methodSymbol)) { // ... ignore some methods that are irrelevant return(newProgramState); } if (methodSymbol.IsExtensionMethod) { // Extension methods could modify the collection, hence we remove the Empty constraint if present return(collectionSymbol.RemoveConstraint(CollectionCapacityConstraint.Empty, newProgramState)); } if (AddMethods.Contains(methodSymbol.Name)) { // ... set constraint if we are adding items newProgramState = collectionSymbol.SetConstraint(CollectionCapacityConstraint.NotEmpty, newProgramState); } else { // ... notify we are accessing the collection OnCollectionAccessed(invocation, collectionSymbol.HasConstraint(CollectionCapacityConstraint.Empty, newProgramState)); } } return(newProgramState); }
private ProgramState ProcessInvocation(ProgramState programState, InvocationExpressionSyntax invocation) { var newProgramState = RemoveCollectionConstraintsFromArguments(invocation, programState); var memberAccess = invocation.Expression as MemberAccessExpressionSyntax; if (memberAccess == null) { return(newProgramState); } var collectionSymbol = semanticModel.GetSymbolInfo(memberAccess.Expression).Symbol; var collectionType = GetCollectionType(collectionSymbol); // When invoking a collection method ... if (collectionType.IsAny(TrackedCollectionTypes)) { var methodSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; if (IsIgnoredMethod(methodSymbol)) { // ... ignore some methods that are irrelevant return(newProgramState); } if (AddMethods.Contains(methodSymbol.Name)) { // ... set constraint if we are adding items newProgramState = collectionSymbol.SetConstraint(CollectionCapacityConstraint.NotEmpty, newProgramState); } else { // ... notify we are accessing the collection OnCollectionAccessed(invocation, collectionSymbol.HasConstraint(CollectionCapacityConstraint.Empty, newProgramState)); } } return(newProgramState); }