summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/api/Position.scala
blob: 2e02d4a26f2f3170a4f11f1389901ac69646e6a0 (plain) (blame)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package scala
package reflect
package api

import scala.reflect.macros.Attachments

/**
 *  <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
 *
 *  Position tracks the origin of [[Symbols#Symbol symbols]] and [[Trees#Tree tree nodes]]. They are commonly used when
 *  displaying warnings and errors, to indicate the incorrect point in the program.
 *
 *  Every non-empty position refers to a SourceFile and three character
 *  offsets within it: start, end, and point. The point is where the ^ belongs when
 *  issuing an error message, usually a Name. A range position can be designated
 *  as transparent, which excuses it from maintaining the invariants to follow. If
 *  a transparent position has opaque children, those are considered as if they were
 *  the direct children of the transparent position's parent.
 *
 *  Note: some of these invariants actually apply to the trees which carry
 *  the positions, but they are phrased as if the positions themselves were
 *  the parent/children for conciseness.
 *
 *  Invariant 1: in a focused/offset position, start == point == end
 *  Invariant 2: in a range position,          start <= point <  end
 *  Invariant 3: an offset position never has a child with a range position
 *  Invariant 4: every range position child of a range position parent is contained within its parent
 *  Invariant 5: opaque range position siblings overlap at most at a single point
 *
 *  The following tests are useful on positions:
 *
 *  pos.isDefined     true if position is not an UndefinedPosition (those being NoPosition and FakePos)
 *  pos.isRange       true if position is a range (opaque or transparent) which implies start < end
 *  pos.isOpaqueRange true if position is an opaque range
 *
 *  The following accessor methods are provided - an exception will be thrown if
 *  point/start/end are attempted on an UndefinedPosition.
 *
 *  pos.source       The source file of the position, or NoSourceFile if unavailable
 *  pos.point        The offset of the point
 *  pos.start        The (inclusive) start offset, or the point of an offset position
 *  pos.end          The (exclusive) end offset, or the point of an offset position
 *
 *  The following conversion methods are often used:
 *
 *  pos.focus           Converts a range position to an offset position focused on the point
 *  pos.makeTransparent Convert an opaque range into a transparent range
 *
 *  For more information about `Position`s, see the [[http://docs.scala-lang.org/overviews/reflection/annotations-names-scopes.html Reflection Guide: Annotations, Names, Scopes, and More]]
 *
 *  @groupname Common   Commonly used methods
 *  @group ReflectionAPI
 */
trait Position extends Attachments {

  /** @inheritdoc */
  type Pos >: Null <: AnyRef with Position

  ////////////////// POSITION FLAVORS //////////////////

  /** Is this position a range position? */
  def isRange: Boolean

  /** Is this position a transparent position? */
  def isTransparent: Boolean

  /** Is this position a non-transparent range position? */
  def isOpaqueRange: Boolean

  /** If this is a range position, the offset position of its point.
   *  Otherwise the position itself
   */
  def focus: Pos

  /** If opaque range, make this position transparent. */
  def makeTransparent: Pos

  ////////////////// POSITION ESSENTIALS //////////////////

  /** The start of the position's range, or the point if not a range position. */
  def start: Int

  /** The point (where the ^ is) of the position, which is easiest to access using the [[line]] and [[column]] values.
   *  The [[lineContent line content]] is also available.
   *  @group Common
   */
  def point: Int

  /** The end of the position's range, or the point if not a range position.
   */
  def end: Int

  /** Java file corresponding to the source file of this position.
   *
   *  The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
   *  It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
   *  and exposed as a part of scala.reflect.api.
   *
   *  @group Common
   */
  def source: scala.reflect.internal.util.SourceFile

  /** The position indicates a [[column `column`]] and the `line` in the source file.
   *  @group Common
   */
  def line: Int

  /** The position indicates a `column` and the [[line `line`]] in the source file.
   *  @group Common
   */
  def column: Int

  ////////////////// POSITION FACTORIES //////////////////

  /** Returns a new position with the same attributes, but a different start value (if a range).
   */
  def withStart(off: Int): Pos

  /** Returns a new position with the same attributes, but a different end value (if a range).
   */
  def withEnd(off: Int): Pos

  /** Returns a new position with the same attributes, but a different point value (if a range or offset).
   */
  def withPoint(off: Int): Pos

  ////////////////// STUFF //////////////////

  /** Is this position not a NoPosition?
   *  If isDefined is true, offset and source are both defined.
   *  @group Common
   */
  @deprecated("removed from the public API", "2.11.0") def isDefined: Boolean

  /** The point (where the ^ is) of the position, or else `default` if undefined.
   *  @group Common
   */
  @deprecated("removed from the public API", "2.11.0") def pointOrElse(default: Int): Int

  /** The start of the position's range, or point if not a range position. */
  @deprecated("removed from the public API", "2.11.0") def startOrPoint: Int

  /** The end of the position's range, or point if not a range position.
   */
  @deprecated("removed from the public API", "2.11.0") def endOrPoint: Int

  /** If this is a range, the union with the other range, with the point of this position.
   *  Otherwise, this position
   */
  @deprecated("removed from the public API", "2.11.0") def union(pos: Pos): Pos

  /** If this is a range position, the offset position of its start.
   *  Otherwise the position itself
   */
  @deprecated("removed from the public API", "2.11.0") def focusStart: Pos

  /** If this is a range position, the offset position of its end.
   *  Otherwise the position itself
   */
  @deprecated("removed from the public API", "2.11.0") def focusEnd: Pos

  /** Does this position include the given position `pos`?
   *  This holds if `this` is a range position and its range [start..end]
   *  is the same or covers the range of the given position, which may or may not be a range position.
   */
  @deprecated("removed from the public API", "2.11.0") def includes(pos: Pos): Boolean

  /** Does this position properly include the given position `pos` ("properly" meaning their
   *  ranges are not the same)?
   */
  @deprecated("removed from the public API", "2.11.0") def properlyIncludes(pos: Pos): Boolean

  /** Does this position precede that position?
   *  This holds if both positions are defined and the end point of this position
   *  is not larger than the start point of the given position.
   */
  @deprecated("removed from the public API", "2.11.0") def precedes(pos: Pos): Boolean

  /** Does this position properly precede the given position `pos` ("properly" meaning their ranges
   *  do not share a common point).
   */
  @deprecated("removed from the public API", "2.11.0") def properlyPrecedes(pos: Pos): Boolean

  /** Does this position overlap with that position?
   *  This holds if both positions are ranges and there is an interval of
   *  non-zero length that is shared by both position ranges.
   */
  @deprecated("removed from the public API", "2.11.0") def overlaps(pos: Pos): Boolean

  /** Does this position cover the same range as that position?
   *  Holds only if both position are ranges
   */
  @deprecated("removed from the public API", "2.11.0") def sameRange(pos: Pos): Boolean

  /** Convert this to a position around `point` that spans a single source line
   */
  @deprecated("removed from the public API", "2.11.0") def toSingleLine: Pos

  /** The content of the line this Position refers to.
   *  @group Common
   */
  @deprecated("removed from the public API", "2.11.0") def lineContent: String

  /** Show a textual representation of the position.
   */
  @deprecated("use `universe.show(position)` instead", "2.11.0") def show: String
}