bring back CodeContracts to mobile profiles.
[mono-project.git] / mcs / class / corlib / System.Diagnostics.Contracts.Internal / ContractHelper.cs
blob64bd9822d6d4b6da5086c3e045e47a5eff6b3d19
1 //
2 // System.Diagnostics.Contracts.Internal.ContractHelper.cs
3 //
4 // Authors:
5 // Chris Bacon (chrisbacon76@gmail.com)
6 //
7 // Copyright 2010 Novell (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #if NET_4_0 || NET_2_1
31 using System;
32 using System.Text;
33 using System.Reflection;
34 using System.Runtime.ConstrainedExecution;
36 namespace System.Diagnostics.Contracts.Internal
38 #if NET_4_5
39 [Obsolete ("Type has been moved to System.Runtime.CompilerServices")]
40 #endif
41 public static class ContractHelper
43 #if MOONLIGHT
44 const string SystemWindowsBrowser = ", System.Windows.Browser, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e";
45 const string HtmlPage = "System.Windows.Browser.HtmlPage" + SystemWindowsBrowser;
46 const string HtmlWindow = "System.Windows.Browser.HtmlWindow" + SystemWindowsBrowser;
47 static MethodInfo alert;
48 static object window;
50 static ContractHelper ()
52 Type htmlpage = Type.GetType (HtmlPage);
53 MethodInfo get_window = htmlpage.GetMethod ("get_Window", BindingFlags.Static | BindingFlags.Public);
54 window = get_window.Invoke (null, null);
55 Type htmlwindow = Type.GetType (HtmlWindow);
56 alert = htmlwindow.GetMethod ("Alert", BindingFlags.Instance | BindingFlags.Public);
58 #endif
60 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
61 [DebuggerNonUserCode]
62 public static string RaiseContractFailedEvent (ContractFailureKind failureKind, string userMessage, string conditionText, Exception innerException)
65 StringBuilder msg = new StringBuilder (60);
66 switch (failureKind) {
67 case ContractFailureKind.Assert:
68 msg.Append ("Assertion failed");
69 break;
70 case ContractFailureKind.Assume:
71 msg.Append ("Assumption failed");
72 break;
73 case ContractFailureKind.Invariant:
74 msg.Append ("Invariant failed");
75 break;
76 case ContractFailureKind.Postcondition:
77 msg.Append ("Postcondition failed");
78 break;
79 case ContractFailureKind.PostconditionOnException:
80 msg.Append ("Postcondition failed after throwing an exception");
81 break;
82 case ContractFailureKind.Precondition:
83 msg.Append ("Precondition failed");
84 break;
85 default:
86 throw new NotSupportedException ("Not supported: " + failureKind);
88 if (conditionText != null) {
89 msg.Append (": ");
90 msg.Append (conditionText);
91 } else {
92 msg.Append ('.');
94 if (userMessage != null) {
95 msg.Append (" ");
96 msg.Append (userMessage);
98 string msgString = msg.ToString ();
100 Exception handlerException = null;
101 bool unwind = false, handled = false;
103 var contractFailed = Contract.InternalContractFailedEvent;
104 if (contractFailed != null) {
105 // Execute all event handlers
106 var handlers = contractFailed.GetInvocationList ();
107 var e = new ContractFailedEventArgs (failureKind, msgString, conditionText, innerException);
108 foreach (var handler in handlers) {
109 try {
110 handler.DynamicInvoke (null, e);
111 } catch (Exception ex) {
112 e.SetUnwind ();
113 // If multiple handlers throw an exception then the specification states that it
114 // is undetermined which one becomes the InnerException.
115 handlerException = ex.InnerException;
118 unwind = e.Unwind;
119 handled = e.Handled;
122 if (unwind) {
123 Exception ex = innerException ?? handlerException;
124 throw new ContractException (msgString, failureKind, conditionText, userMessage, ex);
127 return handled ? null : msgString;
130 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
131 [DebuggerNonUserCode]
132 public static void TriggerFailure (ContractFailureKind kind, string displayMessage, string userMessage, string conditionText, Exception innerException)
134 StringBuilder msg = new StringBuilder (50);
136 if (conditionText != null) {
137 msg.Append ("Expression: ");
138 msg.AppendLine (conditionText);
140 msg.Append ("Description: ");
141 if (displayMessage != null) {
142 msg.Append (displayMessage);
144 #if MOONLIGHT
145 // Silverlight shows a dialog that let you Abort (kill process/browser), Retry or Ignore
146 // Moonlight will simply warn and ignore (at least until FailFast is implemented)
147 // using reflection into System.Windows.Browser to popup an browser alert
148 alert.Invoke (window, new object [] { msg.ToString () });
149 #else
150 if (Environment.UserInteractive) {
151 // FIXME: This should trigger an assertion.
152 // But code will never get here at the moment, as Environment.UserInteractive currently
153 // always returns false.
154 throw new ContractShouldAssertException (msg.ToString ());
155 } else {
156 // Note that FailFast() currently throws a NotImplementedException()
157 Environment.FailFast(msg.ToString()/*, new ExecutionEngineException()*/);
159 #endif
166 #endif