From 4efe998b76fa471c04c15e1a4f05ab858be8deb8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 15 Feb 2018 14:58:01 +0100 Subject: [PATCH 1/2] Harden IDE: Catch NoSuchFileException A NoSuchFileException was observed for a non-existing directory on the classpath: /Users/odersky/workspace/dotty/compiler/../out/bootstrap/dotty-compiler-bootstrapped/scala-0.7/classes It was after a dotty-bootstrapped/clean. I believe this should be ignored, or maybe handled with an error message. But certainly not a crash. --- .../dotc/interactive/InteractiveDriver.scala | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index 3940547ffa81..8d2b0f434c64 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -148,20 +148,24 @@ class InteractiveDriver(settings: List[String]) extends Driver { val names = new mutable.ListBuffer[String] dirClassPaths.foreach { dirCp => val root = dirCp.dir.toPath - Files.walkFileTree(root, new SimpleFileVisitor[Path] { - override def visitFile(path: Path, attrs: BasicFileAttributes) = { - if (!attrs.isDirectory) { - val name = path.getFileName.toString - for { - tastySuffix <- tastySuffixes - if name.endsWith(tastySuffix) - } { - names += root.relativize(path).toString.replace("/", ".").stripSuffix(tastySuffix) + try + Files.walkFileTree(root, new SimpleFileVisitor[Path] { + override def visitFile(path: Path, attrs: BasicFileAttributes) = { + if (!attrs.isDirectory) { + val name = path.getFileName.toString + for { + tastySuffix <- tastySuffixes + if name.endsWith(tastySuffix) + } { + names += root.relativize(path).toString.replace("/", ".").stripSuffix(tastySuffix) + } } + FileVisitResult.CONTINUE } - FileVisitResult.CONTINUE - } - }) + }) + catch { + case _: NoSuchFileException => + } } names.toList } From 86c762079b86b1c0f18493edb2ce59b96a470eee Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 17 Feb 2018 18:37:44 +0100 Subject: [PATCH 2/2] Make pathTo operation more robust Paths can contain non-tree elements. I observed a path that contained an untpd.Mod instead of a tree. Also, we should survive possible cyclic references when ccomputing the context of a path. (this was also observed in the wild but I can't reproduce it). --- .../src/dotty/tools/dotc/interactive/Interactive.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index e884429b97cd..0e1456764088 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -344,7 +344,7 @@ object Interactive { if (tree.pos.contains(pos)) { // FIXME: We shouldn't need a cast. Change NavigateAST.pathTo to return a List of Tree? val path = NavigateAST.pathTo(pos, tree, skipZeroExtent = true).asInstanceOf[List[untpd.Tree]] - path.dropWhile(!_.hasType).asInstanceOf[List[tpd.Tree]] + path.dropWhile(!_.hasType) collect { case t: tpd.Tree @unchecked => t } } else Nil @@ -365,7 +365,7 @@ object Interactive { case nested :: encl :: rest => import typer.Typer._ val outer = contextOfPath(encl :: rest) - encl match { + try encl match { case tree @ PackageDef(pkg, stats) => assert(tree.symbol.exists) if (nested `eq` pkg) outer @@ -401,6 +401,9 @@ object Interactive { case _ => outer } + catch { + case ex: CyclicReference => outer + } } /** The first tree in the path that is a definition. */