Skip to content

Commit 25d2f7b

Browse files
authored
Support absolute path source locators (#5111)
The default behavior of Scala-cli is to use a Bloop server running in the root directory for compilation. This results in absolute paths in for source locators at compile time, but our logic had assumed we always had relative paths and was manually stripping the leading forward slash in source locator paths. Instead, we strip the leading forward slash for relative paths by including it in the path prefix we remove, and then in error reporting we add support for paths that are already absolute.
1 parent ef64c67 commit 25d2f7b

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

core/src/main/scala-2/chisel3/internal/SourceInfoFileResolver.scala

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package chisel3.internal.sourceinfo
55
import scala.language.experimental.macros
66
import scala.reflect.macros.blackbox.Context
77

8+
import java.io.File.separatorChar
9+
810
///////////////////////////////////////////////////////
911
// WARNING!! //
1012
// This file is soft-linked into the compiler plugin //
@@ -13,13 +15,18 @@ import scala.reflect.macros.blackbox.Context
1315

1416
/** Scala compile-time function for determine the String used to represent a source file path in SourceInfos */
1517
private[internal] object SourceInfoFileResolver {
18+
// Ensure non-empty paths end in a slash
19+
def sanitizePath(path: String): String = {
20+
if (path.isEmpty) path
21+
else if (path.last != separatorChar) path + separatorChar
22+
else path
23+
}
24+
1625
def resolve(source: scala.reflect.internal.util.SourceFile): String = {
1726
val userDir = sys.props.get("user.dir") // Figure out what to do if not provided
1827
val projectRoot = sys.props.get("chisel.project.root")
19-
val root = projectRoot.orElse(userDir)
28+
val root = projectRoot.orElse(userDir).map(sanitizePath)
2029

21-
val path = root.map(r => source.file.canonicalPath.stripPrefix(r)).getOrElse(source.file.name)
22-
val pathNoStartingSlash = if (path(0) == '/') path.tail else path
23-
pathNoStartingSlash
30+
root.map(r => source.file.canonicalPath.stripPrefix(r)).getOrElse(source.file.name)
2431
}
2532
}

core/src/main/scala/chisel3/internal/Error.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ object ExceptionHelpers {
3232
private[chisel3] def getErrorLineInFile(sourceRoots: Seq[File], sl: SourceLine): List[String] = {
3333
def tryFileInSourceRoot(sourceRoot: File): Option[List[String]] = {
3434
try {
35-
val file = new File(sourceRoot, sl.filename)
35+
val file = {
36+
val f = new File(sl.filename)
37+
// Absolute paths are not relative to sourceRoot.
38+
if (f.isAbsolute) f
39+
else new File(sourceRoot, sl.filename)
40+
}
3641
val lines = Source.fromFile(file).getLines()
3742
var i = 0
3843
while (i < (sl.line - 1) && lines.hasNext) {

lit/tests/ErrorCarat.sc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: JDK_JAVA_OPTIONS='-Dchisel.project.root=' not scala-cli --server=false --java-home=%JAVAHOME --extra-jars=%RUNCLASSPATH --scala-version=%SCALAVERSION --scala-option="-Xplugin:%SCALAPLUGINJARS" %s | FileCheck %s
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import chisel3._
5+
6+
class ModuleWithError extends Module {
7+
val in = IO(Input(UInt(8.W)))
8+
val out = IO(Output(UInt(16.W)))
9+
10+
// Check behavior of absolute path source locators due to chisel.project.root set to empty above.
11+
// CHECK: High index 15 is out of range [0, 7]
12+
// CHECK-NEXT: out := in(15, 0)
13+
// CHECK-NEXT: ^
14+
out := in(15, 0)
15+
}
16+
17+
circt.stage.ChiselStage.emitCHIRRTL(new ModuleWithError)

0 commit comments

Comments
 (0)