summaryrefslogtreecommitdiff
path: root/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/io/FileVirtualFiles.scala
blob: da29225fbea43f1969807fbecdfab34f9ee4a87b (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
package scala.scalajs.tools.io

import scala.annotation.tailrec

import java.io._
import java.net.URI

/** A [[VirtualFile]] implemented by an actual file on the file system. */
class FileVirtualFile(val file: File) extends VirtualFile {
  import FileVirtualFile._

  override def path = file.getPath

  override def name = file.getName

  override def version: Option[String] = {
    if (!file.isFile) None
    else Some(file.lastModified.toString)
  }

  override def exists: Boolean = file.exists

  override def toURI: URI = file.toURI
}

object FileVirtualFile extends (File => FileVirtualFile) {
  def apply(f: File): FileVirtualFile =
    new FileVirtualFile(f)

  /** Tests whether the given file has the specified extension.
   *  Extension contain the '.', so a typical value for `ext` would be ".js".
   *  The comparison is case-sensitive.
   */
  def hasExtension(file: File, ext: String): Boolean =
    file.getName.endsWith(ext)

  /** Returns a new file with the same parent as the given file but a different
   *  name.
   */
  def withName(file: File, newName: String): File =
    new File(file.getParentFile(), newName)

  /** Returns a new file with the same path as the given file but a different
   *  extension.
   *  Extension contain the '.', so a typical value for `ext` would be ".js".
   *  Precondition: hasExtension(file, oldExt)
   */
  def withExtension(file: File, oldExt: String, newExt: String): File = {
    require(hasExtension(file, oldExt),
        s"File $file does not have extension '$oldExt'")
    withName(file, file.getName.stripSuffix(oldExt) + newExt)
  }
}

/** A [[VirtualTextFile]] implemented by an actual file on the file system. */
class FileVirtualTextFile(f: File) extends FileVirtualFile(f)
                                      with VirtualTextFile {
  import FileVirtualTextFile._

  override def content: String = readFileToString(file)
  override def reader: Reader = new BufferedReader(new FileReader(f))
}

object FileVirtualTextFile extends (File => FileVirtualTextFile) {
  def apply(f: File): FileVirtualTextFile =
    new FileVirtualTextFile(f)

  /** Reads the entire content of a file as a UTF-8 string. */
  def readFileToString(file: File): String = {
    val stream = new FileInputStream(file)
    try IO.readInputStreamToString(stream)
    finally stream.close()
  }
}

trait WritableFileVirtualTextFile extends FileVirtualTextFile
                                     with WritableVirtualTextFile {
  override def contentWriter: Writer = {
    new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(file), "UTF-8"))
  }
}

object WritableFileVirtualTextFile {
  def apply(f: File): WritableFileVirtualTextFile =
    new FileVirtualTextFile(f) with WritableFileVirtualTextFile
}

/** A [[VirtualBinaryFile]] implemented by an actual file on the file system. */
class FileVirtualBinaryFile(f: File) extends FileVirtualFile(f)
                                        with VirtualBinaryFile {
  import FileVirtualBinaryFile._

  override def inputStream: InputStream =
    new BufferedInputStream(new FileInputStream(file))

  override def content: Array[Byte] =
    readFileToByteArray(file)
}

object FileVirtualBinaryFile extends (File => FileVirtualBinaryFile) {
  def apply(f: File): FileVirtualBinaryFile =
    new FileVirtualBinaryFile(f)

  /** Reads the entire content of a file as byte array. */
  def readFileToByteArray(file: File): Array[Byte] = {
    val stream = new FileInputStream(file)
    try IO.readInputStreamToByteArray(stream)
    finally stream.close()
  }
}

class FileVirtualJSFile(f: File) extends FileVirtualTextFile(f)
                                    with VirtualJSFile {
  import FileVirtualFile._
  import FileVirtualTextFile._

  val sourceMapFile: File = withExtension(file, ".js", ".js.map")

  override def sourceMap: Option[String] = {
    if (sourceMapFile.exists) Some(readFileToString(sourceMapFile))
    else None
  }
}

object FileVirtualJSFile extends (File => FileVirtualJSFile) {
  def apply(f: File): FileVirtualJSFile =
    new FileVirtualJSFile(f)
}

trait WritableFileVirtualJSFile extends FileVirtualJSFile
                                   with WritableFileVirtualTextFile
                                   with WritableVirtualJSFile {

  override def sourceMapWriter: Writer = {
    new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(sourceMapFile), "UTF-8"))
  }
}

object WritableFileVirtualJSFile {
  def apply(f: File): WritableFileVirtualJSFile =
    new FileVirtualJSFile(f) with WritableFileVirtualJSFile
}

class FileVirtualScalaJSIRFile(f: File)
    extends FileVirtualBinaryFile(f) with VirtualSerializedScalaJSIRFile

object FileVirtualScalaJSIRFile extends (File => FileVirtualScalaJSIRFile) {
  import FileVirtualFile._

  def apply(f: File): FileVirtualScalaJSIRFile =
    new FileVirtualScalaJSIRFile(f)

  def isScalaJSIRFile(file: File): Boolean =
    hasExtension(file, ".sjsir")
}