1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
15 using System; using Microsoft;
18 using System.Diagnostics;
20 using System.Dynamic.Utils;
22 using Microsoft.Scripting.Utils;
26 namespace System.Linq.Expressions {
28 namespace Microsoft.Linq.Expressions {
31 /// Emits or clears a sequence point for debug information.
33 /// This allows the debugger to highlight the correct source code when
37 [DebuggerTypeProxy(typeof(Expression.DebugInfoExpressionProxy))]
39 public class DebugInfoExpression : Expression {
41 private readonly SymbolDocumentInfo _document;
43 internal DebugInfoExpression(SymbolDocumentInfo document) {
48 /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
50 /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
51 public sealed override Type Type {
52 get { return typeof(void); }
56 /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
58 /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
59 public sealed override ExpressionType NodeType {
60 get { return ExpressionType.DebugInfo; }
64 /// Gets the start line of this <see cref="DebugInfoExpression" />.
66 public virtual int StartLine {
67 get { throw ContractUtils.Unreachable; }
71 /// Gets the start column of this <see cref="DebugInfoExpression" />.
73 public virtual int StartColumn {
74 get { throw ContractUtils.Unreachable; }
78 /// Gets the end line of this <see cref="DebugInfoExpression" />.
80 public virtual int EndLine {
81 get { throw ContractUtils.Unreachable; }
85 /// Gets the end column of this <see cref="DebugInfoExpression" />.
87 public virtual int EndColumn {
88 get { throw ContractUtils.Unreachable; }
92 /// Gets the <see cref="SymbolDocumentInfo"/> that represents the source file.
94 public SymbolDocumentInfo Document {
95 get { return _document; }
99 /// Gets the value to indicate if the <see cref="DebugInfoExpression"/> is for clearing a sequence point.
101 public virtual bool IsClear {
102 get { throw ContractUtils.Unreachable; }
105 internal override Expression Accept(ExpressionVisitor visitor) {
106 return visitor.VisitDebugInfo(this);
110 #region Specialized subclasses
112 internal sealed class SpanDebugInfoExpression : DebugInfoExpression {
113 private readonly int _startLine, _startColumn, _endLine, _endColumn;
115 internal SpanDebugInfoExpression(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn)
117 _startLine = startLine;
118 _startColumn = startColumn;
120 _endColumn = endColumn;
123 public override int StartLine {
129 public override int StartColumn {
135 public override int EndLine {
141 public override int EndColumn {
147 public override bool IsClear {
153 internal override Expression Accept(ExpressionVisitor visitor) {
154 return visitor.VisitDebugInfo(this);
158 internal sealed class ClearDebugInfoExpression : DebugInfoExpression {
159 internal ClearDebugInfoExpression(SymbolDocumentInfo document)
163 public override bool IsClear {
169 public override int StartLine {
175 public override int StartColumn {
181 public override int EndLine {
187 public override int EndColumn {
195 public partial class Expression {
197 /// Creates a <see cref="DebugInfoExpression"/> with the specified span.
199 /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
200 /// <param name="startLine">The start line of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
201 /// <param name="startColumn">The start column of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
202 /// <param name="endLine">The end line of this <see cref="DebugInfoExpression" />. Must be greater or equal than the start line.</param>
203 /// <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>
204 /// <returns>An instance of <see cref="DebugInfoExpression"/>.</returns>
205 public static DebugInfoExpression DebugInfo(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn) {
206 ContractUtils.RequiresNotNull(document, "document");
207 if (startLine == 0xfeefee && startColumn == 0 && endLine == 0xfeefee && endColumn == 0) {
208 return new ClearDebugInfoExpression(document);
211 ValidateSpan(startLine, startColumn, endLine, endColumn);
212 return new SpanDebugInfoExpression(document, startLine, startColumn, endLine, endColumn);
216 /// Creates a <see cref="DebugInfoExpression"/> for clearing a sequence point.
218 /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
219 /// <returns>An instance of <see cref="DebugInfoExpression"/> for clearning a sequence point.</returns>
220 public static DebugInfoExpression ClearDebugInfo(SymbolDocumentInfo document) {
221 ContractUtils.RequiresNotNull(document, "document");
223 return new ClearDebugInfoExpression(document);
226 private static void ValidateSpan(int startLine, int startColumn, int endLine, int endColumn) {
228 throw Error.OutOfRange("startLine", 1);
230 if (startColumn < 1) {
231 throw Error.OutOfRange("startColumn", 1);
234 throw Error.OutOfRange("endLine", 1);
237 throw Error.OutOfRange("endColumn", 1);
239 if (startLine > endLine) {
240 throw Error.StartEndMustBeOrdered();
242 if (startLine == endLine && startColumn > endColumn) {
243 throw Error.StartEndMustBeOrdered();