Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Dynamic / Utils / ContractUtils.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Apache License, Version 2.0, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 #if FEATURE_CORE_DLR
17 using System.Linq.Expressions;
18 #else
19 using Microsoft.Scripting.Ast;
20 #endif
21
22 using System;
23 using System.Collections;
24 using System.Collections.Generic;
25 using System.Diagnostics;
26
27 namespace Microsoft.Scripting.Utils {
28     public static class ContractUtils {
29         [Conditional("DEBUG")]
30         public static void Assert(bool precondition) {
31             Debug.Assert(precondition);
32         }
33
34         public static void Requires(bool precondition) {
35             if (!precondition) {
36                 throw new ArgumentException(Strings.MethodPreconditionViolated);
37             }
38         }
39
40         public static void Requires(bool precondition, string paramName) {
41             Utils.Assert.NotEmpty(paramName);
42
43             if (!precondition) {
44                 throw new ArgumentException(Strings.InvalidArgumentValue, paramName);
45             }
46         }
47
48         public static void Requires(bool precondition, string paramName, string message) {
49             Utils.Assert.NotEmpty(paramName);
50
51             if (!precondition) {
52                 throw new ArgumentException(message, paramName);
53             }
54         }
55
56         public static void RequiresNotNull(object value, string paramName) {
57             Utils.Assert.NotEmpty(paramName);
58
59             if (value == null) {
60                 throw new ArgumentNullException(paramName);
61             }
62         }
63
64         public static void RequiresNotEmpty(string str, string paramName) {
65             RequiresNotNull(str, paramName);
66             if (str.Length == 0) {
67                 throw new ArgumentException(Strings.NonEmptyStringRequired, paramName);
68             }
69         }
70
71         public static void RequiresNotEmpty<T>(ICollection<T> collection, string paramName) {
72             RequiresNotNull(collection, paramName);
73             if (collection.Count == 0) {
74                 throw new ArgumentException(Strings.NonEmptyCollectionRequired, paramName);
75             }
76         }
77
78         /// <summary>
79         /// Requires the specified index to point inside the array.
80         /// </summary>
81         /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
82         /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
83         public static void RequiresArrayIndex<T>(IList<T> array, int index, string indexName) {
84             RequiresArrayIndex(array.Count, index, indexName);
85         }
86
87         /// <summary>
88         /// Requires the specified index to point inside the array.
89         /// </summary>
90         /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
91         public static void RequiresArrayIndex(int arraySize, int index, string indexName) {
92             Utils.Assert.NotEmpty(indexName);
93             Debug.Assert(arraySize >= 0);
94
95             if (index < 0 || index >= arraySize) throw new ArgumentOutOfRangeException(indexName);
96         }
97
98         /// <summary>
99         /// Requires the specified index to point inside the array or at the end
100         /// </summary>
101         /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
102         /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
103         public static void RequiresArrayInsertIndex<T>(IList<T> array, int index, string indexName) {
104             RequiresArrayInsertIndex(array.Count, index, indexName);
105         }
106
107         /// <summary>
108         /// Requires the specified index to point inside the array or at the end
109         /// </summary>
110         /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
111         /// <exception cref="ArgumentOutOfRangeException">Index is outside the array.</exception>
112         public static void RequiresArrayInsertIndex(int arraySize, int index, string indexName) {
113             Utils.Assert.NotEmpty(indexName);
114             Debug.Assert(arraySize >= 0);
115
116             if (index < 0 || index > arraySize) throw new ArgumentOutOfRangeException(indexName);
117         }
118
119         /// <summary>
120         /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
121         /// </summary>
122         /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
123         public static void RequiresArrayRange<T>(IList<T> array, int offset, int count, string offsetName, string countName) {
124             Utils.Assert.NotNull(array);
125             RequiresArrayRange(array.Count, offset, count, offsetName, countName);
126         }
127
128         /// <summary>
129         /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
130         /// </summary>
131         /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
132         public static void RequiresArrayRange(int arraySize, int offset, int count, string offsetName, string countName) {
133             Utils.Assert.NotEmpty(offsetName);
134             Utils.Assert.NotEmpty(countName);
135             Debug.Assert(arraySize >= 0);
136
137             if (count < 0) throw new ArgumentOutOfRangeException(countName);
138             if (offset < 0 || arraySize - offset < count) throw new ArgumentOutOfRangeException(offsetName);
139         }
140
141
142         /// <summary>
143         /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
144         /// </summary>
145         /// <exception cref="ArgumentNullException">Array is <c>null</c>.</exception>
146         /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
147         public static void RequiresListRange(IList array, int offset, int count, string offsetName, string countName) {
148             Utils.Assert.NotEmpty(offsetName);
149             Utils.Assert.NotEmpty(countName);
150             Utils.Assert.NotNull(array);
151
152             if (count < 0) throw new ArgumentOutOfRangeException(countName);
153             if (offset < 0 || array.Count - offset < count) throw new ArgumentOutOfRangeException(offsetName);
154         }
155
156         /// <summary>
157         /// Requires the range [offset, offset + count] to be a subset of [0, array.Count].
158         /// </summary>
159         /// <exception cref="ArgumentNullException">String is <c>null</c>.</exception>
160         /// <exception cref="ArgumentOutOfRangeException">Offset or count are out of range.</exception>
161         public static void RequiresArrayRange(string str, int offset, int count, string offsetName, string countName) {
162             Utils.Assert.NotEmpty(offsetName);
163             Utils.Assert.NotEmpty(countName);
164             Utils.Assert.NotNull(str);
165
166             if (count < 0) throw new ArgumentOutOfRangeException(countName);
167             if (offset < 0 || str.Length - offset < count) throw new ArgumentOutOfRangeException(offsetName);
168         }
169
170         /// <summary>
171         /// Requires the array and all its items to be non-null.
172         /// </summary>
173         public static void RequiresNotNullItems<T>(IList<T> array, string arrayName) {
174             Utils.Assert.NotNull(arrayName);
175             RequiresNotNull(array, arrayName);
176
177             for (int i = 0; i < array.Count; i++) {
178                 if (array[i] == null) {
179                     throw ExceptionUtils.MakeArgumentItemNullException(i, arrayName);
180                 }
181             }
182         }
183                 
184         /// <summary>
185         /// Requires the enumerable collection and all its items to be non-null.
186         /// </summary>
187         public static void RequiresNotNullItems<T>(IEnumerable<T> collection, string collectionName) {
188             Utils.Assert.NotNull(collectionName);
189             RequiresNotNull(collection, collectionName);
190
191             int i = 0;
192             foreach (var item in collection) {
193                 if (item == null) {
194                     throw ExceptionUtils.MakeArgumentItemNullException(i, collectionName);
195                 }
196                 i++;
197             }
198         }
199
200         [Conditional("FALSE")]
201         public static void Invariant(bool condition) {
202             Debug.Assert(condition);
203         }
204
205         [Conditional("FALSE")]
206         public static void Invariant(bool condition, string message) {
207             Debug.Assert(condition, message);
208         }
209
210         [Conditional("FALSE")]
211         public static void Ensures(bool condition) {
212             // nop
213         }
214
215         [Conditional("FALSE")]
216         public static void Ensures(bool condition, string message) {
217             // nop
218         }
219
220         public static T Result<T>() { 
221             return default(T); 
222         }
223
224         public static T Parameter<T>(out T value) { 
225             value = default(T); 
226             return value; 
227         }
228
229         public static T Old<T>(T value) { 
230             return value; 
231         }
232     }
233 }