Skip to content

Commit 76eac60

Browse files
committed
Merge pull request scala#4191 from som-snytt/issue/8538
SI-8538 Test or example for Source.report
2 parents c924a64 + 5343c13 commit 76eac60

File tree

2 files changed

+100
-3
lines changed

2 files changed

+100
-3
lines changed

src/library/scala/io/Source.scala

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,20 @@ object Source {
169169
createBufferedSource(is, reset = () => fromInputStream(is)(codec), close = () => is.close())(codec)
170170
}
171171

172-
/** The class `Source` implements an iterable representation of source data.
173-
* Calling method `reset` returns an identical, resetted source, where
174-
* possible.
172+
/** An iterable representation of source data.
173+
* It may be reset with the optional `reset` method.
174+
*
175+
* Subclasses must supply [[scala.io.Source@iter the underlying iterator]].
176+
*
177+
* Error handling may be customized by overriding the [[scala.io.Source@report report]] method.
178+
*
179+
* The [[scala.io.Source@ch current input]] and [[scala.io.Source@pos position]],
180+
* as well as the [[scala.io.Source@next next character]] methods delegate to
181+
* [[scala.io.Source$Positioner the positioner]].
182+
*
183+
* The default positioner encodes line and column numbers in the position passed to `report`.
184+
* This behavior can be changed by supplying a
185+
* [[scala.io.Source@withPositioning(pos:Source.this.Positioner):Source.this.type custom positioner]].
175186
*
176187
* @author Burak Emir
177188
* @version 1.0

test/junit/scala/io/SourceTest.scala

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
package scala.io
3+
4+
import org.junit.Test
5+
import org.junit.Assert._
6+
import org.junit.runner.RunWith
7+
import org.junit.runners.JUnit4
8+
9+
import scala.tools.testing.AssertUtil._
10+
11+
import java.io.{ Console => _, _ }
12+
13+
@RunWith(classOf[JUnit4])
14+
class SourceTest {
15+
16+
private implicit val `our codec` = Codec.UTF8
17+
private val charSet = Codec.UTF8.charSet.name
18+
19+
private def sampler = """
20+
|Big-endian and little-endian approaches aren't
21+
|readily interchangeable in general, because the
22+
|laws of arithmetic send signals leftward from
23+
|the bits that are "least significant."
24+
|""".stripMargin.trim
25+
26+
private def in = new ByteArrayInputStream(sampler.getBytes)
27+
28+
@Test def canIterateLines() = {
29+
assertEquals(sampler.lines.size, (Source fromString sampler).getLines.size)
30+
}
31+
@Test def canCustomizeReporting() = {
32+
class CapitalReporting(is: InputStream) extends BufferedSource(is) {
33+
override def report(pos: Int, msg: String, out: PrintStream): Unit = {
34+
out print f"$pos%04x: ${msg.toUpperCase}"
35+
}
36+
class OffsetPositioner extends Positioner(null) {
37+
override def next(): Char = {
38+
ch = iter.next()
39+
pos = pos + 1
40+
ch
41+
}
42+
}
43+
withPositioning(new OffsetPositioner)
44+
}
45+
val s = new CapitalReporting(in)
46+
// skip to next line and report an error
47+
do {
48+
val c = s.next()
49+
} while (s.ch != '\n')
50+
s.next()
51+
val out = new ByteArrayOutputStream
52+
val ps = new PrintStream(out, true, charSet)
53+
s.reportError(s.pos, "That doesn't sound right.", ps)
54+
assertEquals("0030: THAT DOESN'T SOUND RIGHT.", out.toString(charSet))
55+
}
56+
@Test def canAltCustomizeReporting() = {
57+
class CapitalReporting(is: InputStream)(implicit codec: Codec) extends Source {
58+
override val iter = {
59+
val r = new InputStreamReader(is, codec.decoder)
60+
Iterator continually (codec wrap r.read()) takeWhile (_ != -1) map (_.toChar)
61+
}
62+
override def report(pos: Int, msg: String, out: PrintStream): Unit = {
63+
out print f"$pos%04x: ${msg.toUpperCase}"
64+
}
65+
private[this] var _pos: Int = _
66+
override def pos = _pos
67+
private[this] var _ch: Char = _
68+
override def ch = _ch
69+
override def next = {
70+
_ch = iter.next()
71+
_pos += 1
72+
_ch
73+
}
74+
}
75+
val s = new CapitalReporting(in)
76+
// skip to next line and report an error
77+
do {
78+
val c = s.next()
79+
} while (s.ch != '\n')
80+
s.next()
81+
val out = new ByteArrayOutputStream
82+
val ps = new PrintStream(out, true, charSet)
83+
s.reportError(s.pos, "That doesn't sound right.", ps)
84+
assertEquals("0030: THAT DOESN'T SOUND RIGHT.", out.toString(charSet))
85+
}
86+
}

0 commit comments

Comments
 (0)