BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / DebugInfoExpression.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 using System;
17 using System.Diagnostics;
18 using System.Dynamic.Utils;
19
20 #if SILVERLIGHT
21 using System.Core;
22 #endif
23
24 #if CLR2
25 namespace Microsoft.Scripting.Ast {
26 #else
27 namespace System.Linq.Expressions {
28 #endif
29     /// <summary>
30     /// Emits or clears a sequence point for debug information.
31     /// 
32     /// This allows the debugger to highlight the correct source code when
33     /// debugging.
34     /// </summary>
35 #if !SILVERLIGHT
36     [DebuggerTypeProxy(typeof(Expression.DebugInfoExpressionProxy))]
37 #endif
38     public class DebugInfoExpression : Expression {
39
40         private readonly SymbolDocumentInfo _document;
41
42         internal DebugInfoExpression(SymbolDocumentInfo document) {
43             _document = document;
44         }
45
46         /// <summary>
47         /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
48         /// </summary>
49         /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
50         public sealed override Type Type {
51             get { return typeof(void); }
52         }
53
54         /// <summary>
55         /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
56         /// </summary>
57         /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
58         public sealed override ExpressionType NodeType {
59             get { return ExpressionType.DebugInfo; }
60         }
61
62         /// <summary>
63         /// Gets the start line of this <see cref="DebugInfoExpression" />.
64         /// </summary>
65         public virtual int StartLine {
66             get { throw ContractUtils.Unreachable; }
67         }
68
69         /// <summary>
70         /// Gets the start column of this <see cref="DebugInfoExpression" />.
71         /// </summary>
72         public virtual int StartColumn {
73             get { throw ContractUtils.Unreachable; }
74         }
75
76         /// <summary>
77         /// Gets the end line of this <see cref="DebugInfoExpression" />.
78         /// </summary>
79         public virtual int EndLine {
80             get { throw ContractUtils.Unreachable; }
81         }
82
83         /// <summary>
84         /// Gets the end column of this <see cref="DebugInfoExpression" />.
85         /// </summary>
86         public virtual int EndColumn {
87             get { throw ContractUtils.Unreachable; }
88         }
89
90         /// <summary>
91         /// Gets the <see cref="SymbolDocumentInfo"/> that represents the source file.
92         /// </summary>
93         public SymbolDocumentInfo Document {
94             get { return _document; }
95         }
96
97         /// <summary>
98         /// Gets the value to indicate if the <see cref="DebugInfoExpression"/> is for clearing a sequence point.
99         /// </summary>
100         public virtual bool IsClear {
101             get { throw ContractUtils.Unreachable; }
102         }
103
104         /// <summary>
105         /// Dispatches to the specific visit method for this node type.
106         /// </summary>
107         protected internal override Expression Accept(ExpressionVisitor visitor) {
108             return visitor.VisitDebugInfo(this);
109         }
110     }
111
112     #region Specialized subclasses
113
114     internal sealed class SpanDebugInfoExpression : DebugInfoExpression {
115         private readonly int _startLine, _startColumn, _endLine, _endColumn;
116
117         internal SpanDebugInfoExpression(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn)
118             : base(document) {
119             _startLine = startLine;
120             _startColumn = startColumn;
121             _endLine = endLine;
122             _endColumn = endColumn;
123         }
124
125         public override int StartLine {
126             get {
127                 return _startLine;
128             }
129         }
130
131         public override int StartColumn {
132             get {
133                 return _startColumn;
134             }
135         }
136
137         public override int EndLine {
138             get {
139                 return _endLine;
140             }
141         }
142
143         public override int EndColumn {
144             get {
145                 return _endColumn;
146             }
147         }
148
149         public override bool IsClear {
150             get {
151                 return false;
152             }
153         }
154
155         protected internal override Expression Accept(ExpressionVisitor visitor) {
156             return visitor.VisitDebugInfo(this);
157         }
158     }
159
160     internal sealed class ClearDebugInfoExpression : DebugInfoExpression {
161         internal ClearDebugInfoExpression(SymbolDocumentInfo document)
162             : base(document) {
163         }
164
165         public override bool IsClear {
166             get {
167                 return true;
168             }
169         }
170
171         public override int StartLine {
172             get {
173                 return 0xfeefee;
174             }
175         }
176
177         public override int StartColumn {
178             get {
179                 return 0;
180             }
181         }
182
183         public override int EndLine {
184             get {
185                 return 0xfeefee;
186             }
187         }
188
189         public override int EndColumn {
190             get {
191                 return 0;
192             }
193         }
194     }
195     #endregion
196
197     public partial class Expression {
198         /// <summary>
199         /// Creates a <see cref="DebugInfoExpression"/> with the specified span.
200         /// </summary>
201         /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
202         /// <param name="startLine">The start line of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
203         /// <param name="startColumn">The start column of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
204         /// <param name="endLine">The end line of this <see cref="DebugInfoExpression" />. Must be greater or equal than the start line.</param>
205         /// <param name="endColumn">The end column of this <see cref="DebugInfoExpression" />. If the end line is the same as the start line, it must be greater or equal than the start column. In any case, must be greater than 0.</param>
206         /// <returns>An instance of <see cref="DebugInfoExpression"/>.</returns>
207         public static DebugInfoExpression DebugInfo(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn) {
208             ContractUtils.RequiresNotNull(document, "document");
209             if (startLine == 0xfeefee && startColumn == 0 && endLine == 0xfeefee && endColumn == 0) {
210                 return new ClearDebugInfoExpression(document);
211             }
212
213             ValidateSpan(startLine, startColumn, endLine, endColumn);
214             return new SpanDebugInfoExpression(document, startLine, startColumn, endLine, endColumn);
215         }
216
217         /// <summary>
218         /// Creates a <see cref="DebugInfoExpression"/> for clearing a sequence point.
219         /// </summary>
220         /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
221         /// <returns>An instance of <see cref="DebugInfoExpression"/> for clearning a sequence point.</returns>
222         public static DebugInfoExpression ClearDebugInfo(SymbolDocumentInfo document) {
223             ContractUtils.RequiresNotNull(document, "document");
224
225             return new ClearDebugInfoExpression(document);
226         }
227
228         private static void ValidateSpan(int startLine, int startColumn, int endLine, int endColumn) {
229             if (startLine < 1) {
230                 throw Error.OutOfRange("startLine", 1);
231             }
232             if (startColumn < 1) {
233                 throw Error.OutOfRange("startColumn", 1);
234             }
235             if (endLine < 1) {
236                 throw Error.OutOfRange("endLine", 1);
237             }
238             if (endColumn < 1) {
239                 throw Error.OutOfRange("endColumn", 1);
240             }
241             if (startLine > endLine) {
242                 throw Error.StartEndMustBeOrdered();
243             }
244             if (startLine == endLine && startColumn > endColumn) {
245                 throw Error.StartEndMustBeOrdered();
246             }
247         }
248     }
249 }