199 lines
6.6 KiB
C#
199 lines
6.6 KiB
C#
|
//-----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.Activities.Debugger
|
||
|
{
|
||
|
using System;
|
||
|
using System.Activities.Debugger.Symbol;
|
||
|
using System.Diagnostics;
|
||
|
using System.Linq;
|
||
|
using System.Runtime;
|
||
|
|
||
|
// Identifies a specific location in the target source code.
|
||
|
//
|
||
|
// This source information is used in creating PDBs, which will be passed to the debugger,
|
||
|
// which will resolve the source file based off its own source paths.
|
||
|
// Source ranges can:
|
||
|
// * refer to just an entire single line.
|
||
|
// * can be a subset within a single line (when StartLine == EndLine)
|
||
|
// * can also span multiple lines.
|
||
|
// When column info is provided, the debugger will highlight the characters starting at the start line and start column,
|
||
|
// and going up to but not including the character specified by the end line and end column.
|
||
|
[Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Our partial trust mechanisms require that this class remain Immutable. Do not add code that allows an instance of this class to change after creation without strict review.")]
|
||
|
[DebuggerNonUserCode]
|
||
|
[Serializable]
|
||
|
[Fx.Tag.XamlVisible(false)]
|
||
|
public class SourceLocation
|
||
|
{
|
||
|
string fileName;
|
||
|
int startLine;
|
||
|
int endLine;
|
||
|
int startColumn;
|
||
|
int endColumn;
|
||
|
byte[] checksum;
|
||
|
|
||
|
// Define a source location from a filename and line-number (1-based).
|
||
|
// This is a convenience constructor to specify the entire line.
|
||
|
// This does not load the source file to determine column ranges.
|
||
|
public SourceLocation(string fileName, int line)
|
||
|
: this(fileName, line, 1, line, int.MaxValue)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public SourceLocation(
|
||
|
string fileName,
|
||
|
int startLine,
|
||
|
int startColumn,
|
||
|
int endLine,
|
||
|
int endColumn)
|
||
|
: this(fileName, null, startLine, startColumn, endLine, endColumn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// Define a source location in a file.
|
||
|
// Line/Column are 1-based.
|
||
|
internal SourceLocation(
|
||
|
string fileName,
|
||
|
byte[] checksum,
|
||
|
int startLine,
|
||
|
int startColumn,
|
||
|
int endLine,
|
||
|
int endColumn)
|
||
|
{
|
||
|
if (startLine <= 0)
|
||
|
{
|
||
|
throw FxTrace.Exception.Argument("startLine", SR.InvalidSourceLocationLineNumber("startLine", startLine));
|
||
|
}
|
||
|
|
||
|
if (startColumn <= 0)
|
||
|
{
|
||
|
throw FxTrace.Exception.Argument("startColumn", SR.InvalidSourceLocationColumn("startColumn", startColumn));
|
||
|
}
|
||
|
|
||
|
if (endLine <= 0)
|
||
|
{
|
||
|
throw FxTrace.Exception.Argument("endLine", SR.InvalidSourceLocationLineNumber("endLine", endLine));
|
||
|
}
|
||
|
|
||
|
if (endColumn <= 0)
|
||
|
{
|
||
|
throw FxTrace.Exception.Argument("endColumn", SR.InvalidSourceLocationColumn("endColumn", endColumn));
|
||
|
}
|
||
|
|
||
|
if (startLine > endLine)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("endLine", endLine, SR.OutOfRangeSourceLocationEndLine(startLine));
|
||
|
}
|
||
|
|
||
|
if ((startLine == endLine) && (startColumn > endColumn))
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("endColumn", endColumn, SR.OutOfRangeSourceLocationEndColumn(startColumn));
|
||
|
}
|
||
|
|
||
|
this.fileName = (fileName != null) ? fileName.ToUpperInvariant() : null;
|
||
|
this.startLine = startLine;
|
||
|
this.endLine = endLine;
|
||
|
this.startColumn = startColumn;
|
||
|
this.endColumn = endColumn;
|
||
|
this.checksum = checksum;
|
||
|
}
|
||
|
|
||
|
public string FileName
|
||
|
{
|
||
|
get { return this.fileName; }
|
||
|
}
|
||
|
|
||
|
// Get the 1-based start line.
|
||
|
public int StartLine
|
||
|
{
|
||
|
get { return this.startLine; }
|
||
|
}
|
||
|
|
||
|
// Get the 1-based starting column.
|
||
|
public int StartColumn
|
||
|
{
|
||
|
get { return this.startColumn; }
|
||
|
}
|
||
|
|
||
|
// Get the 1-based end line. This should be greater or equal to StartLine.
|
||
|
public int EndLine
|
||
|
{
|
||
|
get { return this.endLine; }
|
||
|
}
|
||
|
|
||
|
// Get the 1-based ending column.
|
||
|
public int EndColumn
|
||
|
{
|
||
|
get { return this.endColumn; }
|
||
|
}
|
||
|
|
||
|
// get the checksum of the source file
|
||
|
internal byte[] Checksum
|
||
|
{
|
||
|
get { return this.checksum; }
|
||
|
}
|
||
|
|
||
|
public bool IsSingleWholeLine
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.endColumn == int.MaxValue && this.startLine == this.endLine && this.startColumn == 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Equality comparison function. This checks for strict equality and
|
||
|
// not for superset or subset relationships.
|
||
|
public override bool Equals(object obj)
|
||
|
{
|
||
|
SourceLocation rsl = obj as SourceLocation;
|
||
|
if (rsl == null)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (this.FileName != rsl.FileName)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (this.StartLine != rsl.StartLine ||
|
||
|
this.StartColumn != rsl.StartColumn ||
|
||
|
this.EndLine != rsl.EndLine ||
|
||
|
this.EndColumn != rsl.EndColumn)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (this.Checksum == null ^ rsl.Checksum == null)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
else if ((this.Checksum != null && rsl.Checksum != null) && !this.Checksum.SequenceEqual(rsl.Checksum))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// everything matches
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Get a hash code.
|
||
|
public override int GetHashCode()
|
||
|
{
|
||
|
return (string.IsNullOrEmpty(this.FileName) ? 0 : this.FileName.GetHashCode()) ^
|
||
|
this.StartLine.GetHashCode() ^
|
||
|
this.StartColumn.GetHashCode() ^
|
||
|
((this.Checksum == null) ? 0 : SymbolHelper.GetHexStringFromChecksum(this.Checksum).GetHashCode());
|
||
|
}
|
||
|
|
||
|
internal static bool IsValidRange(int startLine, int startColumn, int endLine, int endColumn)
|
||
|
{
|
||
|
return
|
||
|
(startLine > 0) && (startColumn > 0) && (endLine > 0) && (endColumn > 0) &&
|
||
|
((startLine < endLine) || (startLine == endLine) && (startColumn < endColumn));
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|