Skip to content

Commit a306462

Browse files
authored
Merge pull request #1494 from martijnhoekstra/wintests
[WIP] fix encoding issues
2 parents 93d4c8c + 46b3253 commit a306462

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+84
-36
lines changed

.gitattributes

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
# These files are text and should be normalized (convert crlf => lf)
2-
*.c text
3-
*.check text
4-
*.css text
5-
*.html text
6-
*.java text
7-
*.js text
8-
*.sbt text
9-
*.scala text
10-
*.sh text
11-
*.txt text
12-
*.xml text
2+
3+
*.c text eol=lf
4+
*.check text eol=lf
5+
*.css text eol=lf
6+
*.html text eol=lf
7+
*.java text eol=lf
8+
*.js text eol=lf
9+
*.sbt text eol=lf
10+
*.scala text eol=lf
11+
*.sh text eol=lf
12+
*.txt text eol=lf
13+
*.xml text eol=lf
1314

1415
# Windows-specific files get windows endings
1516
*.bat eol=crlf

dottydoc/test/BaseTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import model.Package
1212
trait DottyTest {
1313
dotty.tools.dotc.parsing.Scanners // initialize keywords
1414

15-
implicit var ctx: FreshContext = {
15+
implicit val ctx: FreshContext = {
1616
val base = new ContextBase
1717
import base.settings._
1818
val ctx = base.initialCtx.fresh

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ object DottyBuild extends Build {
4040
homepage in Global := Some(url("https://github.com/lampepfl/dotty")),
4141

4242
// scalac options
43-
scalacOptions in Global ++= Seq("-feature", "-deprecation", "-language:existentials,higherKinds,implicitConversions"),
43+
scalacOptions in Global ++= Seq("-feature", "-deprecation", "-encoding", "UTF8", "-language:existentials,higherKinds,implicitConversions"),
4444

4545
javacOptions in Global ++= Seq("-Xlint:unchecked", "-Xlint:deprecation")
4646
)

src/dotty/tools/dotc/Run.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Phases._
99
import Decorators._
1010
import dotty.tools.dotc.transform.TreeTransforms.TreeTransformer
1111
import io.PlainFile
12+
import scala.io.Codec
1213
import util._
1314
import reporting.Reporter
1415
import transform.TreeChecker
@@ -28,8 +29,9 @@ class Run(comp: Compiler)(implicit ctx: Context) {
2829
var units: List[CompilationUnit] = _
2930

3031
def getSource(fileName: String): SourceFile = {
32+
val encoding = ctx.settings.encoding.value
3133
val f = new PlainFile(fileName)
32-
if (f.exists) new SourceFile(f)
34+
if (f.exists) new SourceFile(f, Codec(encoding))
3335
else {
3436
ctx.error(s"not found: $fileName")
3537
NoSource
@@ -113,7 +115,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
113115
val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8")) // buffering is still advised by javadoc
114116
writer.write(sourceCode)
115117
writer.close()
116-
compileSources(List(new SourceFile(virtualFile)))
118+
compileSources(List(new SourceFile(virtualFile, Codec.UTF8)))
117119
}
118120

119121
/** The context created for this run */

src/dotty/tools/dotc/config/Settings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ object Settings {
2525
private var values = ArrayBuffer(initialValues: _*)
2626
private var _wasRead: Boolean = false
2727

28+
override def toString = s"SettingsState(values: ${values.toList})"
29+
2830
def value(idx: Int): Any = {
2931
_wasRead = true
3032
values(idx)

src/dotty/tools/dotc/util/SourceFile.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import java.io.IOException
1010
import Chars._
1111
import ScriptSourceFile._
1212
import Positions._
13+
import scala.io.Codec
1314

1415
import java.util.Optional
1516

@@ -36,9 +37,9 @@ object ScriptSourceFile {
3637

3738
case class SourceFile(file: AbstractFile, content: Array[Char]) extends interfaces.SourceFile {
3839

39-
def this(_file: AbstractFile) = this(_file, _file.toCharArray)
40-
def this(sourceName: String, cs: Seq[Char]) = this(new VirtualFile(sourceName), cs.toArray)
41-
def this(file: AbstractFile, cs: Seq[Char]) = this(file, cs.toArray)
40+
def this(_file: AbstractFile, codec: Codec) = this(_file, new String(_file.toByteArray, codec.charSet).toCharArray)
41+
def this(sourceName: String, cs: Seq[Char]) = this(new VirtualFile(sourceName), cs.toArray)
42+
def this(file: AbstractFile, cs: Seq[Char]) = this(file, cs.toArray)
4243

4344
/** Tab increment; can be overridden */
4445
def tabInc = 8

test/dotc/tests.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ class tests extends CompilerTest {
2323
val defaultOutputDir = "./out/"
2424

2525
implicit val defaultOptions = noCheckOptions ++ List(
26-
"-Yno-deep-subtypes", "-Yno-double-bindings", "-Yforce-sbt-phases",
27-
"-d", defaultOutputDir) ++ {
26+
"-Yno-deep-subtypes", "-Yno-double-bindings", "-Yforce-sbt-phases", "-d", defaultOutputDir) ++ {
2827
if (isRunByJenkins) List("-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef") // should be Ycheck:all, but #725
2928
else List("-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef")
3029
}
@@ -38,6 +37,9 @@ class tests extends CompilerTest {
3837
val allowDoubleBindings = defaultOptions diff List("-Yno-double-bindings")
3938
val scala2mode = List("-language:Scala2")
4039

40+
val explicitUTF8 = List("-encoding", "UTF8")
41+
val explicitUTF16 = List("-encoding", "UTF16")
42+
4143
val testsDir = "./tests/"
4244
val posDir = testsDir + "pos/"
4345
val posSpecialDir = testsDir + "pos-special/"
@@ -95,7 +97,7 @@ class tests extends CompilerTest {
9597
@Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess", twice)
9698
@Test def pos_approximateUnion = compileFile(posDir, "approximateUnion", twice)
9799
@Test def pos_tailcall = compileDir(posDir, "tailcall", twice)
98-
@Test def pos_valueclasses = compileFiles(posDir + "valueclasses/", twice)
100+
@Test def pos_valueclasses = compileFiles(posDir + "pos_valueclasses/", twice)
99101
@Test def pos_nullarify = compileFile(posDir, "nullarify", args = "-Ycheck:nullarify" :: Nil)
100102
@Test def pos_subtyping = compileFile(posDir, "subtyping", twice)
101103
@Test def pos_packageObj = compileFile(posDir, "i0239", twice)
@@ -118,6 +120,8 @@ class tests extends CompilerTest {
118120
compileFile(posSpecialDir, "spec-t5545/S_1")
119121
compileFile(posSpecialDir, "spec-t5545/S_2")
120122
}
123+
@Test def pos_utf8 = compileFile(posSpecialDir, "utf8encoded", explicitUTF8)
124+
@Test def pos_utf16 = compileFile(posSpecialDir, "utf16encoded", explicitUTF16)
121125

122126
@Test def new_all = compileFiles(newDir, twice)
123127
@Test def repl_all = replFiles(replDir)

test/test/CompilerTest.scala

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ abstract class CompilerTest {
228228

229229
private def expectedErrors(filePath: String): List[ErrorsInFile] = expectedErrors(List(filePath))
230230

231-
private def isNegTest(testPath: String) = testPath.contains(JFile.separator + "neg" + JFile.separator)
231+
private def isNegTest(testPath: String) = testPath.contains("/neg/")
232232

233233
private def compileArgs(args: Array[String], expectedErrorsPerFile: List[ErrorsInFile])
234234
(implicit defaultOptions: List[String]): Unit = {
@@ -413,7 +413,8 @@ abstract class CompilerTest {
413413
val flags = oldFlags.map(f => if (f == oldOutput) partestOutput else f) ++
414414
List(s"-classpath $partestOutput") // Required for separate compilation tests
415415

416-
getExisting(dest).isDifferent(source, flags, nerr) match {
416+
val difference = getExisting(dest).isDifferent(source, flags, nerr)
417+
difference match {
417418
case NotExists => copyFiles(source, dest, partestOutput, flags, nerr, kind)
418419
case ExistsSame => // nothing else to do
419420
case ExistsDifferent =>
@@ -449,11 +450,37 @@ abstract class CompilerTest {
449450
/** Recursively copy over source files and directories, excluding extensions
450451
* that aren't in extensionsToCopy. */
451452
private def recCopyFiles(sourceFile: Path, dest: Path): Unit = {
452-
processFileDir(sourceFile, { sf =>
453+
454+
def copyfile(file: SFile, bytewise: Boolean): Unit = {
455+
if (bytewise) {
456+
val in = file.inputStream()
457+
val out = SFile(dest).outputStream()
458+
val buffer = new Array[Byte](1024)
459+
def loop(available: Int):Unit = {
460+
if (available < 0) {()}
461+
else {
462+
out.write(buffer, 0, available)
463+
val read = in.read(buffer)
464+
loop(read)
465+
}
466+
}
467+
loop(0)
468+
in.close()
469+
out.close()
470+
} else {
471+
try {
472+
SFile(dest)(scala.io.Codec.UTF8).writeAll((s"/* !!!!! WARNING: DO NOT MODIFY. Original is at: $file !!!!! */").replace("\\", "/"), file.slurp("UTF-8"))
473+
} catch {
474+
case unmappable: java.nio.charset.MalformedInputException =>
475+
copyfile(file, true) //there are bytes that can't be mapped with UTF-8. Bail and just do a straight byte-wise copy without the warning header.
476+
}
477+
}
478+
}
479+
480+
processFileDir(sourceFile, { sf =>
453481
if (extensionsToCopy.contains(sf.extension)) {
454482
dest.parent.jfile.mkdirs
455-
dest.toFile.writeAll("/* !!!!! WARNING: DO NOT MODIFY. Original is at: $sf !!!!! */",
456-
sf.slurp())
483+
copyfile(sf, false)
457484
} else {
458485
log(s"WARNING: ignoring $sf")
459486
}
@@ -465,7 +492,7 @@ abstract class CompilerTest {
465492

466493
/** Reads the existing files for the given test source if any. */
467494
private def getExisting(dest: Path): ExistingFiles = {
468-
val content: Option[Option[String]] = processFileDir(dest, f => f.safeSlurp, d => Some(""))
495+
val content: Option[Option[String]] = processFileDir(dest, f => try Some(f.slurp("UTF8")) catch {case io: java.io.IOException => Some(io.toString())}, d => Some(""))
469496
if (content.isDefined && content.get.isDefined) {
470497
val flags = (dest changeExtension "flags").toFile.safeSlurp
471498
val nerr = (dest changeExtension "nerr").toFile.safeSlurp
@@ -479,7 +506,7 @@ abstract class CompilerTest {
479506
if (!genSrc.isDefined) {
480507
NotExists
481508
} else {
482-
val source = processFileDir(sourceFile, { f => f.safeSlurp }, { d => Some("") },
509+
val source = processFileDir(sourceFile, { f => try Some(f.slurp("UTF8")) catch {case _: java.io.IOException => None} }, { d => Some("") },
483510
Some("DPCompilerTest sourceFile doesn't exist: " + sourceFile)).get
484511
if (source == genSrc) {
485512
nerr match {

test/test/DottyTest.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class DottyTest /*extends ContextEscapeDetection*/ {
2323
import base.settings._
2424
val ctx = base.initialCtx.fresh
2525
base.initialize()(ctx)
26+
ctx.setSetting(ctx.settings.encoding, "UTF8")
2627
ctx
2728
}
2829
/*

test/test/InterfaceEntryPointTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import scala.collection.mutable.ListBuffer
1818
*/
1919
class InterfaceEntryPointTest {
2020
@Test def runCompilerFromInterface = {
21-
val sources = List("./tests/pos/HelloWorld.scala")
21+
val sources = List("./tests/pos/HelloWorld.scala").map(p => new java.io.File(p).getPath())
2222
val args = sources ++ List("-d", "./out/")
2323

2424
val mainClass = Class.forName("dotty.tools.dotc.Main")

test/test/OtherEntryPointsTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import scala.collection.mutable.ListBuffer
1717
*/
1818
class OtherEntryPointsTest {
1919
@Test def runCompiler = {
20-
val sources = List("./tests/pos/HelloWorld.scala")
20+
val sources = List("./tests/pos/HelloWorld.scala").map(p => new java.io.File(p).getPath())
2121
val args = sources ++ List("-d", "./out/")
2222

2323
val reporter = new CustomReporter
@@ -31,7 +31,7 @@ class OtherEntryPointsTest {
3131
}
3232

3333
@Test def runCompilerWithContext = {
34-
val sources = List("./tests/pos/HelloWorld.scala")
34+
val sources = List("./tests/pos/HelloWorld.scala").map(p => new java.io.File(p).getPath())
3535
val args = sources ++ List("-d", "./out/")
3636

3737
val reporter = new CustomReporter

test/test/ParserTest.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import scala.reflect.io._
44
import dotty.tools.dotc.util._
55
import dotty.tools.dotc.core._
66
import dotty.tools.dotc.parsing._
7+
import scala.io.Codec
78
import Tokens._, Parsers._
89
import dotty.tools.dotc.ast.untpd._
910
import org.junit.Test
@@ -23,7 +24,7 @@ class ParserTest extends DottyTest {
2324

2425
def parse(file: PlainFile): Tree = {
2526
//println("***** parsing " + file)
26-
val source = new SourceFile(file)
27+
val source = new SourceFile(file, Codec.UTF8)
2728
val parser = new Parser(source)
2829
val tree = parser.parse()
2930
parsed += 1

test/test/ScannerTest.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package test
22

33
import scala.reflect.io._
4+
import scala.io.Codec
45
import dotty.tools.dotc.util._
56
import dotty.tools.dotc.parsing._
67
import Tokens._, Scanners._
@@ -16,8 +17,8 @@ class ScannerTest extends DottyTest {
1617
def scan(name: String): Unit = scan(new PlainFile(name))
1718

1819
def scan(file: PlainFile): Unit = {
19-
println("***** scanning " + file)
20-
val source = new SourceFile(file)
20+
//println("***** scanning " + file)
21+
val source = new SourceFile(file, Codec.UTF8)
2122
val scanner = new Scanner(source)
2223
var i = 0
2324
while (scanner.token != EOF) {

test/test/TestREPL.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class TestREPL(script: String) extends REPL {
3434
while (lines.hasNext && lines.head.startsWith(continuationPrompt)) {
3535
val continued = lines.next
3636
output.println(continued)
37-
buf append "\n"
37+
buf append System.lineSeparator()
3838
buf append continued.drop(continuationPrompt.length)
3939
}
4040
buf.toString
@@ -49,7 +49,7 @@ class TestREPL(script: String) extends REPL {
4949
out.close()
5050
val printed = out.toString
5151
val transcript = printed.drop(printed.indexOf(config.prompt))
52-
if (transcript.toString != script) {
52+
if (transcript.toString.lines.toList != script.lines.toList) {
5353
println("input differs from transcript:")
5454
println(transcript)
5555
assert(false)

tests/pos-special/utf16encoded.scala

324 Bytes
Binary file not shown.

tests/pos-special/utf8encoded.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//this file is saved as UTF-8
2+
object Test {
3+
def main(args: Array[String]): Unit = {
4+
val testchar = '⇒'
5+
println(testchar == '\u21D2')
6+
}
7+
8+
}

0 commit comments

Comments
 (0)