Skip to content

Commit f2937c3

Browse files
committed
Fix broken dotty.tools.io.Path#parent
The previous implementation wrongly assumed that if `jpath.normalize.getParent` returns null, then `jpath` must be a root. However the null in this case really only means that no name elements remain after normalization and the call to `getParent`. Since redundant name elements such as "." and ".." may be removed by `normalize`, and `getParent` may simply remove the last name element, there are cases other than roots to consider, such as the current directory. Some examples of broken behavior prior this commit: scala> Path("./foo.txt").parent val res0: dotty.tools.io.Directory = ./foo.txt // should be Directory(.) scala> Path("foo.txt").parent val res1: dotty.tools.io.Directory = foo.txt // should be Directory(.) scala> Path(".").parent val res4: dotty.tools.io.Directory = . // should be Directory(..) The changes here are based in part on the Scala 2.13 implementation of scala.reflect.io.Path#parent Fixes scala#11644
1 parent f2f877c commit f2937c3

File tree

4 files changed

+41
-1
lines changed

4 files changed

+41
-1
lines changed

compiler/src/dotty/tools/io/Path.scala

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,15 @@ class Path private[io] (val jpath: JPath) {
127127
* @return The path of the parent directory, or root if path is already root
128128
*/
129129
def parent: Directory = jpath.normalize.getParent match {
130-
case null => Directory(jpath)
130+
case null =>
131+
if (isAbsolute) // it should be a root
132+
toDirectory
133+
else if (segments.nonEmpty && segments.last == "..")
134+
(this / "..").toDirectory
135+
else path match {
136+
case "" | "." => Directory("..")
137+
case _ => Directory(".")
138+
}
131139
case parent => Directory(parent)
132140
}
133141
def parents: List[Directory] = {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package dotty.tools.io
2+
3+
import org.junit.Assert._
4+
import org.junit.Test
5+
6+
class PathTest {
7+
// Ref https://github.com/lampepfl/dotty/issues/11644#issuecomment-792457275
8+
@Test def parent(): Unit = {
9+
assertEquals(Directory(".."), Path("").parent)
10+
assertEquals(Directory(".."), Path(".").parent)
11+
assertEquals(Directory("..") / "..", Path("..").parent)
12+
assertEquals(Directory("."), Path("foo.txt").parent)
13+
assertEquals(Directory("."), (Path(".") / "foo.txt").parent)
14+
assertEquals(Directory("."), (Path("bar") / ".").parent)
15+
assertEquals(Directory("."), (Path("foo") / ".." / "." / "bar").parent)
16+
assertEquals(Directory("baz") / "bar", (Path(".") / "baz" / "bar" / "foo.txt").parent)
17+
18+
for (root <- Path.roots) {
19+
val rootDir = Directory(root.path)
20+
assertEquals(rootDir, root.parent)
21+
assertEquals(rootDir, (root / "foo.txt").parent)
22+
assertEquals(rootDir / "baz" / "bar", (root / "baz" / "bar" / "foo.txt").parent)
23+
}
24+
}
25+
}

project/scripts/bootstrapCmdTests

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,9 @@ grep -qe "def main(args: scala.Array\[scala.Predef.String\]): scala.Unit =" "$tm
5858
echo "testing ./bin/scaladoc"
5959
clear_out "$OUT1"
6060
./bin/scaladoc -project Hello -d "$OUT1" "$OUT/out.jar"
61+
62+
# check compilation when the class/tasty files already exist in the current directory
63+
echo "testing i11644"
64+
cwd=$(pwd)
65+
clear_out "$OUT"
66+
(cd "$OUT" && "$cwd/bin/scalac" "$cwd/tests/pos/i11644.scala" && "$cwd/bin/scalac" "$cwd/tests/pos/i11644.scala")

tests/pos/i11644.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@main def hello = println("hello, world")

0 commit comments

Comments
 (0)