Skip to content

Commit 5543104

Browse files
committed
Add List and ListBuffer to stdlib test
Plus all supertraits of ListBuffer
1 parent 0230d03 commit 5543104

14 files changed

+1689
-0
lines changed

tests/pos/stdlib/collection/immutable/List.scala

Lines changed: 693 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection
14+
package mutable
15+
16+
import scala.annotation.nowarn
17+
18+
19+
/** A `Buffer` is a growable and shrinkable `Seq`. */
20+
trait Buffer[A]
21+
extends Seq[A]
22+
with SeqOps[A, Buffer, Buffer[A]]
23+
with Growable[A]
24+
with Shrinkable[A]
25+
with IterableFactoryDefaults[A, Buffer] {
26+
27+
override def iterableFactory: SeqFactory[Buffer] = Buffer
28+
29+
override def knownSize: Int = super[Seq].knownSize
30+
31+
//TODO Prepend is a logical choice for a readable name of `+=:` but it conflicts with the renaming of `append` to `add`
32+
/** Prepends a single element at the front of this $coll.
33+
*
34+
* @param elem the element to $add.
35+
* @return the $coll itself
36+
*/
37+
def prepend(elem: A): this.type
38+
39+
/** Appends the given elements to this buffer.
40+
*
41+
* @param elem the element to append.
42+
*/
43+
@`inline` final def append(elem: A): this.type = addOne(elem)
44+
45+
@deprecated("Use appendAll instead", "2.13.0")
46+
@`inline` final def append(elems: A*): this.type = addAll(elems)
47+
48+
/** Appends the elements contained in a iterable object to this buffer.
49+
* @param xs the iterable object containing the elements to append.
50+
*/
51+
@`inline` final def appendAll(xs: IterableOnce[A]): this.type = addAll(xs)
52+
53+
54+
/** Alias for `prepend` */
55+
@`inline` final def +=: (elem: A): this.type = prepend(elem)
56+
57+
def prependAll(elems: IterableOnce[A]): this.type = { insertAll(0, elems); this }
58+
59+
@deprecated("Use prependAll instead", "2.13.0")
60+
@`inline` final def prepend(elems: A*): this.type = prependAll(elems)
61+
62+
/** Alias for `prependAll` */
63+
@inline final def ++=:(elems: IterableOnce[A]): this.type = prependAll(elems)
64+
65+
/** Inserts a new element at a given index into this buffer.
66+
*
67+
* @param idx the index where the new elements is inserted.
68+
* @param elem the element to insert.
69+
* @throws IndexOutOfBoundsException if the index `idx` is not in the valid range
70+
* `0 <= idx <= length`.
71+
*/
72+
@throws[IndexOutOfBoundsException]
73+
def insert(idx: Int, elem: A): Unit
74+
75+
/** Inserts new elements at the index `idx`. Opposed to method
76+
* `update`, this method will not replace an element with a new
77+
* one. Instead, it will insert a new element at index `idx`.
78+
*
79+
* @param idx the index where a new element will be inserted.
80+
* @param elems the iterable object providing all elements to insert.
81+
* @throws IndexOutOfBoundsException if `idx` is out of bounds.
82+
*/
83+
@throws[IndexOutOfBoundsException]
84+
def insertAll(idx: Int, elems: IterableOnce[A]): Unit
85+
86+
/** Removes the element at a given index position.
87+
*
88+
* @param idx the index which refers to the element to delete.
89+
* @return the element that was formerly at index `idx`.
90+
*/
91+
@throws[IndexOutOfBoundsException]
92+
def remove(idx: Int): A
93+
94+
/** Removes the element on a given index position. It takes time linear in
95+
* the buffer size.
96+
*
97+
* @param idx the index which refers to the first element to remove.
98+
* @param count the number of elements to remove.
99+
* @throws IndexOutOfBoundsException if the index `idx` is not in the valid range
100+
* `0 <= idx <= length - count` (with `count > 0`).
101+
* @throws IllegalArgumentException if `count < 0`.
102+
*/
103+
@throws[IndexOutOfBoundsException]
104+
@throws[IllegalArgumentException]
105+
def remove(idx: Int, count: Int): Unit
106+
107+
/** Removes a single element from this buffer, at its first occurrence.
108+
* If the buffer does not contain that element, it is unchanged.
109+
*
110+
* @param x the element to remove.
111+
* @return the buffer itself
112+
*/
113+
def subtractOne (x: A): this.type = {
114+
val i = indexOf(x)
115+
if (i != -1) remove(i)
116+
this
117+
}
118+
119+
/** Removes the first ''n'' elements of this buffer.
120+
*
121+
* @param n the number of elements to remove from the beginning
122+
* of this buffer.
123+
*/
124+
@deprecated("use dropInPlace instead", since = "2.13.4")
125+
def trimStart(n: Int): Unit = dropInPlace(n)
126+
127+
/** Removes the last ''n'' elements of this buffer.
128+
*
129+
* @param n the number of elements to remove from the end
130+
* of this buffer.
131+
*/
132+
@deprecated("use dropRightInPlace instead", since = "2.13.4")
133+
def trimEnd(n: Int): Unit = dropRightInPlace(n)
134+
135+
def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A], replaced: Int): this.type
136+
137+
// +=, ++=, clear inherited from Growable
138+
// Per remark of @ichoran, we should preferably not have these:
139+
//
140+
// def +=:(elem: A): this.type = { insert(0, elem); this }
141+
// def +=:(elem1: A, elem2: A, elems: A*): this.type = elem1 +=: elem2 +=: elems ++=: this
142+
// def ++=:(elems: IterableOnce[A]): this.type = { insertAll(0, elems); this }
143+
144+
def dropInPlace(n: Int): this.type = { remove(0, normalized(n)); this }
145+
def dropRightInPlace(n: Int): this.type = {
146+
val norm = normalized(n)
147+
remove(length - norm, norm)
148+
this
149+
}
150+
def takeInPlace(n: Int): this.type = {
151+
val norm = normalized(n)
152+
remove(norm, length - norm)
153+
this
154+
}
155+
def takeRightInPlace(n: Int): this.type = { remove(0, length - normalized(n)); this }
156+
def sliceInPlace(start: Int, end: Int): this.type = takeInPlace(end).dropInPlace(start)
157+
private def normalized(n: Int): Int = math.min(math.max(n, 0), length)
158+
159+
def dropWhileInPlace(p: A => Boolean): this.type = {
160+
val idx = indexWhere(!p(_))
161+
if (idx < 0) { clear(); this } else dropInPlace(idx)
162+
}
163+
def takeWhileInPlace(p: A => Boolean): this.type = {
164+
val idx = indexWhere(!p(_))
165+
if (idx < 0) this else takeInPlace(idx)
166+
}
167+
def padToInPlace(len: Int, elem: A): this.type = {
168+
while (length < len) +=(elem)
169+
this
170+
}
171+
172+
@nowarn("""cat=deprecation&origin=scala\.collection\.Iterable\.stringPrefix""")
173+
override protected[this] def stringPrefix = "Buffer"
174+
}
175+
176+
trait IndexedBuffer[A] extends IndexedSeq[A]
177+
with IndexedSeqOps[A, IndexedBuffer, IndexedBuffer[A]]
178+
with Buffer[A]
179+
with IterableFactoryDefaults[A, IndexedBuffer] {
180+
181+
override def iterableFactory: SeqFactory[IndexedBuffer] = IndexedBuffer
182+
183+
def flatMapInPlace(f: A => IterableOnce[A]): this.type = {
184+
// There's scope for a better implementation which copies elements in place.
185+
var i = 0
186+
val s = size
187+
val newElems = new Array[IterableOnce[A]](s)
188+
while (i < s) { newElems(i) = f(this(i)); i += 1 }
189+
clear()
190+
i = 0
191+
while (i < s) { ++=(newElems(i)); i += 1 }
192+
this
193+
}
194+
195+
def filterInPlace(p: A => Boolean): this.type = {
196+
var i, j = 0
197+
while (i < size) {
198+
if (p(apply(i))) {
199+
if (i != j) {
200+
this(j) = this(i)
201+
}
202+
j += 1
203+
}
204+
i += 1
205+
}
206+
207+
if (i == j) this else takeInPlace(j)
208+
}
209+
210+
def patchInPlace(from: Int, patch: scala.collection.IterableOnce[A], replaced: Int): this.type = {
211+
val replaced0 = math.min(math.max(replaced, 0), length)
212+
val i = math.min(math.max(from, 0), length)
213+
var j = 0
214+
val iter = patch.iterator
215+
while (iter.hasNext && j < replaced0 && i + j < length) {
216+
update(i + j, iter.next())
217+
j += 1
218+
}
219+
if (iter.hasNext) insertAll(i + j, iter)
220+
else if (j < replaced0) remove(i + j, math.min(replaced0 - j, length - i - j))
221+
this
222+
}
223+
}
224+
225+
@SerialVersionUID(3L)
226+
object Buffer extends SeqFactory.Delegate[Buffer](ArrayBuffer)
227+
228+
@SerialVersionUID(3L)
229+
object IndexedBuffer extends SeqFactory.Delegate[IndexedBuffer](ArrayBuffer)
230+
231+
/** Explicit instantiation of the `Buffer` trait to reduce class file size in subclasses. */
232+
abstract class AbstractBuffer[A] extends AbstractSeq[A] with Buffer[A]
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection.mutable
14+
15+
import language.experimental.captureChecking
16+
17+
18+
/** Base trait for collection builders.
19+
*
20+
* After calling `result()` the behavior of a Builder (which is not also a [[scala.collection.mutable.ReusableBuilder]])
21+
* is undefined. No further methods should be called. It is common for mutable collections to be their own non-reusable
22+
* Builder, in which case `result()` simply returns `this`.
23+
*
24+
* @see [[scala.collection.mutable.ReusableBuilder]] for Builders which can be reused after calling `result()`
25+
*/
26+
trait Builder[-A, +To] extends Growable[A] {
27+
self: Builder[A, To]^ =>
28+
29+
/** Clears the contents of this builder.
30+
* After execution of this method the builder will contain no elements.
31+
*/
32+
def clear(): Unit
33+
34+
/** Result collection consisting of all elements appended so far. */
35+
def result(): To
36+
37+
/** Gives a hint how many elements are expected to be added
38+
* when the next `result` is called. Some builder classes
39+
* will optimize their representation based on the hint. However,
40+
* builder implementations are still required to work correctly even if the hint is
41+
* wrong, i.e. a different number of elements is added.
42+
*
43+
* @param size the hint how many elements will be added.
44+
*/
45+
def sizeHint(size: Int): Unit = ()
46+
47+
/** Gives a hint that one expects the `result` of this builder
48+
* to have the same size as the given collection, plus some delta. This will
49+
* provide a hint only if the collection has a known size
50+
* Some builder classes
51+
* will optimize their representation based on the hint. However,
52+
* builder implementations are still required to work correctly even if the hint is
53+
* wrong, i.e. a different number of elements is added.
54+
*
55+
* @param coll the collection which serves as a hint for the result's size.
56+
* @param delta a correction to add to the `coll.size` to produce the size hint.
57+
*/
58+
final def sizeHint(coll: scala.collection.IterableOnce[_]^, delta: Int = 0): Unit = {
59+
val s = coll.knownSize
60+
if (s != -1) sizeHint(s + delta)
61+
}
62+
63+
/** Gives a hint how many elements are expected to be added
64+
* when the next `result` is called, together with an upper bound
65+
* given by the size of some other collection. Some builder classes
66+
* will optimize their representation based on the hint. However,
67+
* builder implementations are still required to work correctly even if the hint is
68+
* wrong, i.e. a different number of elements is added.
69+
*
70+
* @param size the hint how many elements will be added.
71+
* @param boundingColl the bounding collection. If it is
72+
* an IndexedSeqLike, then sizes larger
73+
* than collection's size are reduced.
74+
*/
75+
// should probably be `boundingColl: IterableOnce[_]`, but binary compatibility
76+
final def sizeHintBounded(size: Int, boundingColl: scala.collection.Iterable[_]^): Unit = {
77+
val s = boundingColl.knownSize
78+
if (s != -1) {
79+
sizeHint(scala.math.min(s, size))
80+
}
81+
}
82+
83+
/** A builder resulting from this builder my mapping the result using `f`. */
84+
def mapResult[NewTo](f: To => NewTo): Builder[A, NewTo]^{this, f} = new Builder[A, NewTo] {
85+
def addOne(x: A): this.type = { self += x; this }
86+
def clear(): Unit = self.clear()
87+
override def addAll(xs: IterableOnce[A]^): this.type = { self ++= xs; this }
88+
override def sizeHint(size: Int): Unit = self.sizeHint(size)
89+
def result(): NewTo = f(self.result())
90+
override def knownSize: Int = self.knownSize
91+
}
92+
}

0 commit comments

Comments
 (0)