Skip to content

Commit 38c066f

Browse files
Merge pull request #4857 from dotty-staging/fix-scripted
Fix inline scripted
2 parents e24c011 + 40c76d2 commit 38c066f

File tree

5 files changed

+77
-28
lines changed

5 files changed

+77
-28
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
object B {
2-
transparent def getInline: Double =
3-
A.get
2+
transparent def getInline: String =
3+
A.get.toString
44
}

sbt-dotty/sbt-test/source-dependencies/inline/test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ $ copy-file changes/B1.scala B.scala
22
> compile
33

44
$ copy-file changes/B2.scala B.scala
5-
# Compilation of C.scala should fail because B.getInline now has type Double instead of Int
5+
# Compilation of C.scala should fail because B.getInline now has type String instead of Int
66
-> compile
77

88
$ copy-file changes/B1.scala B.scala

sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -112,33 +112,20 @@ object DottyPlugin extends AutoPlugin {
112112
* corresponding .tasty or .hasTasty file is also deleted.
113113
*/
114114
def dottyPatchIncOptions(incOptions: IncOptions): IncOptions = {
115-
val inheritedNewClassFileManager = ClassFileManagerUtil.getDefaultClassFileManager(incOptions)
116-
val tastyFileManager = new ClassFileManager {
117-
private[this] val inherited = inheritedNewClassFileManager
118-
119-
def delete(classes: Array[File]): Unit = {
120-
val tastySuffixes = List(".tasty", ".hasTasty")
121-
inherited.delete(classes flatMap { classFile =>
122-
if (classFile.getPath endsWith ".class") {
123-
val prefix = classFile.getAbsolutePath.stripSuffix(".class")
124-
tastySuffixes.map(suffix => new File(prefix + suffix)).filter(_.exists)
125-
} else Nil
126-
})
127-
}
115+
val tastyFileManager = new TastyFileManager
128116

129-
def generated(classes: Array[File]): Unit = {}
130-
def complete(success: Boolean): Unit = {}
131-
}
117+
// Once sbt/zinc#562 is fixed, can be:
118+
// val newExternalHooks =
119+
// incOptions.externalHooks.withExternalClassFileManager(tastyFileManager)
132120
val inheritedHooks = incOptions.externalHooks
133-
val externalClassFileManager: Optional[ClassFileManager] = Option(inheritedHooks.getExternalClassFileManager.orElse(null)) match {
134-
case Some(prevManager) =>
135-
Optional.of(WrappedClassFileManager.of(prevManager, Optional.of(tastyFileManager)))
136-
case None =>
137-
Optional.of(tastyFileManager)
138-
}
139-
140-
val hooks = new DefaultExternalHooks(inheritedHooks.getExternalLookup, externalClassFileManager)
141-
incOptions.withExternalHooks(hooks)
121+
val external = Optional.of(tastyFileManager: ClassFileManager)
122+
val prevManager = inheritedHooks.getExternalClassFileManager
123+
val fileManager: Optional[ClassFileManager] =
124+
if (prevManager.isPresent) Optional.of(WrappedClassFileManager.of(prevManager.get, external))
125+
else external
126+
val newExternalHooks = new DefaultExternalHooks(inheritedHooks.getExternalLookup, fileManager)
127+
128+
incOptions.withExternalHooks(newExternalHooks)
142129
}
143130

144131
override val globalSettings: Seq[Def.Setting[_]] = Seq(
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package dotty.tools.sbtplugin
2+
3+
import java.io.File
4+
import java.nio.file.Files
5+
6+
import sbt.io.IO
7+
import xsbti.compile.ClassFileManager
8+
9+
import scala.collection.mutable
10+
11+
12+
/** A class file manger that prunes .tasty and .hasTasty as needed.
13+
*
14+
* This makes sure that, when a .class file must be deleted, the
15+
* corresponding .tasty or .hasTasty file is also deleted.
16+
*
17+
* This code is adapted from Zinc `TransactionalClassFileManager`.
18+
* We need to duplicate the logic since forwarding to the default class
19+
* file manager doesn't work: we need to backup tasty files in a different
20+
* temporary directory as class files.
21+
*/
22+
final class TastyFileManager extends ClassFileManager {
23+
private[this] val tempDir = Files.createTempDirectory("backup").toFile
24+
25+
private[this] val generatedTastyFiles = new mutable.HashSet[File]
26+
private[this] val movedTastyFiles = new mutable.HashMap[File, File]
27+
28+
override def delete(classes: Array[File]): Unit = {
29+
val toBeBackedUp = tastyFiles(classes)
30+
.filter(t => t.exists && !movedTastyFiles.contains(t) && !generatedTastyFiles(t))
31+
for (c <- toBeBackedUp)
32+
movedTastyFiles.put(c, move(c))
33+
IO.deleteFilesEmptyDirs(classes)
34+
}
35+
36+
override def generated(classes: Array[File]): Unit =
37+
generatedTastyFiles ++= tastyFiles(classes)
38+
39+
override def complete(success: Boolean): Unit = {
40+
if (!success) {
41+
IO.deleteFilesEmptyDirs(generatedTastyFiles)
42+
for ((orig, tmp) <- movedTastyFiles) IO.move(tmp, orig)
43+
}
44+
IO.delete(tempDir)
45+
}
46+
47+
private def tastyFiles(classes: Array[File]): Array[File] = {
48+
val tastySuffixes = List(".tasty", ".hasTasty")
49+
classes.flatMap { classFile =>
50+
if (classFile.getPath.endsWith(".class")) {
51+
val prefix = classFile.getAbsolutePath.stripSuffix(".class")
52+
tastySuffixes.map(suffix => new File(prefix + suffix)).filter(_.exists)
53+
} else Nil
54+
}
55+
}
56+
57+
private def move(c: File): File = {
58+
val target = File.createTempFile("sbt", ".tasty", tempDir)
59+
IO.move(c, target)
60+
target
61+
}
62+
}

0 commit comments

Comments
 (0)