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