forked from microsoft/python-language-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSourceSpan.cs
More file actions
139 lines (119 loc) · 5.42 KB
/
SourceSpan.cs
File metadata and controls
139 lines (119 loc) · 5.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Python Tools for Visual Studio
// Copyright(c) Microsoft Corporation
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the License); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABILITY OR NON-INFRINGEMENT.
//
// See the Apache Version 2.0 License for specific language governing
// permissions and limitations under the License.
using System;
using System.Diagnostics;
namespace Microsoft.Python.Core.Text {
/// <summary>
/// Stores the location of a span of text in a source file.
/// </summary>
[Serializable]
[DebuggerDisplay("({Start.Line}, {Start.Column})-({End.Line}, {End.Column})")]
public struct SourceSpan: IComparable<SourceSpan> {
/// <summary>
/// Constructs a new span with a specific start and end location.
/// </summary>
/// <param name="start">The beginning of the span.</param>
/// <param name="end">The end of the span.</param>
[DebuggerStepThrough]
public SourceSpan(SourceLocation start, SourceLocation end) {
ValidateLocations(start, end);
Start = start;
End = end;
}
[DebuggerStepThrough]
public SourceSpan(int startLine, int startColumn, int endLine, int endColumn)
: this(new SourceLocation(startLine, startColumn), new SourceLocation(endLine, endColumn)) { }
[DebuggerStepThrough]
private static void ValidateLocations(SourceLocation start, SourceLocation end) {
if (start.IsValid && end.IsValid) {
if (start > end) {
throw new ArgumentException("Start and End must be well ordered");
}
} else {
if (start.IsValid || end.IsValid) {
throw new ArgumentException("Start and End must both be valid or both invalid");
}
}
}
/// <summary>
/// The start location of the span.
/// </summary>
public SourceLocation Start { get; }
/// <summary>
/// The end location of the span. Location of the first character behind the span.
/// </summary>
public SourceLocation End { get; }
/// <summary>
/// A valid span that represents no location.
/// </summary>
public static readonly SourceSpan None = new SourceSpan(SourceLocation.None, SourceLocation.None);
/// <summary>
/// An invalid span.
/// </summary>
public static readonly SourceSpan Invalid = new SourceSpan(SourceLocation.Invalid, SourceLocation.Invalid);
/// <summary>
/// Whether the locations in the span are valid.
/// </summary>
public bool IsValid => Start.IsValid && End.IsValid;
public SourceSpan Union(SourceSpan other) {
var startLine = Math.Min(other.Start.Line, Start.Line);
var startColumn = Math.Min(other.Start.Column, Start.Column);
var endLine = Math.Max(other.End.Line, End.Line);
var endColumn = Math.Max(other.End.Column, End.Column);
return new SourceSpan(new SourceLocation(startLine, startColumn), new SourceLocation(endLine, endColumn));
}
/// <summary>
/// Compares two specified Span values to see if they are equal.
/// </summary>
/// <param name="left">One span to compare.</param>
/// <param name="right">The other span to compare.</param>
/// <returns>True if the spans are the same, False otherwise.</returns>
public static bool operator ==(SourceSpan left, SourceSpan right)
=> left.Start == right.Start && left.End == right.End;
/// <summary>
/// Compares two specified Span values to see if they are not equal.
/// </summary>
/// <param name="left">One span to compare.</param>
/// <param name="right">The other span to compare.</param>
/// <returns>True if the spans are not the same, False otherwise.</returns>
public static bool operator !=(SourceSpan left, SourceSpan right)
=> left.Start != right.Start || left.End != right.End;
public int CompareTo(SourceSpan other) {
if (Start.Line < other.Start.Line) {
return -1;
}
if (Start.Line == other.Start.Line) {
if (Start.Column < other.Start.Column) {
return -1;
}
return Start.Column == other.Start.Column ? 0 : 1;
}
return 1;
}
public override bool Equals(object obj) {
if (!(obj is SourceSpan)) {
return false;
}
var other = (SourceSpan)obj;
return Start == other.Start && End == other.End;
}
public override string ToString() => "{0} - {1}".FormatInvariant(Start, End);
public override int GetHashCode()
// 7 bits for each column (0-128), 9 bits for each row (0-512), xor helps if
// we have a bigger file.
=> (Start.Column) ^ (End.Column << 7) ^ (Start.Line << 14) ^ (End.Line << 23);
}
}