Philipp Haller
30 March 2012
The Scala compiler's error messages would be nearly useless if they wouldn't provide the corresponding source location, that is, file name, line number, and (some representation of the) character offset, of each error. However, source locations are also very useful outside of the compiler. Libraries and frameworks routinely deal with application- or system-level errors (usually in the form of exceptions), logging, debugging support through tracing, etc. All of these aspects greatly benefit from source location information.
Moreover, embedded domain-specific languages often depend upon source location information for providing useful error messages. Domain-specific languages that employ staging for code generation can use source locations for debug information in the generated code.
This proposal discusses a minimal extension of Scala's implicit parameters to provide access to the source location of method invocations. The design is analogous to the way manifests are generated by the compiler, and should therefore be natural to anyone familiar with manifests in Scala.
To obtain the source location for each invocation of a method debug
, say, one adds an implicit parameter of type SourceLocation
:
def debug(message: String)(implicit loc: SourceLocation): Unit = {
println("@" + loc.fileName + ":" + loc.line + ": " + message)
}
This means that inside the body of the debug
method, we can access the source location of its current invocation through the loc
parameter. For example, suppose
we are invoking debug
on line 34
in a file "MyApp.scala"
:
34: if (debugEnabled) debug("debug message")
Assuming debugEnabled
evaluates to true
, the above expression would lead to the following output:
@MyApp.scala:34: debug message
The SourceLocation
trait is a new type member of the scala.reflect
package. It has the following members:
trait SourceLocation {
/** The name of the source file */
def fileName: String
/** The line number */
def line: Int
/** The character offset */
def charOffset: Int
}
Implicit source locations are supported through the following small addition to Scala's implicit rules.
If an implicit parameter of a method or constructor is of type SourceLocation
, a source location object is determined according to the following rules.
First, if there is already an implicit argument of type SourceLocation
, this argument is selected. Otherwise, an instance of SourceLocation
is generated by invoking the apply
method of the object scala.reflect.SourceLocation
, passing the components of the source location as arguments.
An implementation of this proposal can be found at: https://github.com/phaller/scala/tree/topic/source-location
An extension of this proposal is also part of Scala-Virtualized. The extension adds a subtrait SourceContext
which in addition provides access to information, such as variable names in the context of a method invocation. More information can be found at: https://github.com/TiarkRompf/scala-virtualized/wiki/SourceLocation-and-SourceContext
Contents
SIP Committee Decision