Source Utilities
Source utilities provide access to source location information (method name, line number, file path, etc.) at runtime, similar to Python's __name__, C++'s __LINE__, or Ruby's __FILE__. These are useful for debugging, error messages, logging, and providing automatic diagnostics.
Reference Implementation
These utilities are a reference implementation demonstrating how to build sourcecode-like functionality using Hearth's macro API. They are intended to be used outside of macros (in regular application code), not inside macro implementations. The macros expand at the call site to capture source location information, making them usable in any regular Scala code.
If you need source location utilities for production use, consider using the sourcecode library directly, which is more mature and widely used. These utilities serve as a learning example and demonstration of Hearth's capabilities.
Available Utilities
Source utilities expose the following information as implicit/given values:
MethodName: The name of the enclosing method (or<init>for constructors)Line: The current line number in the source fileFile: The full path to the current source fileFileName: Just the filename (without path) of the current source fileLocation: A combination ofFileandLine, useful for error messages
Source utilities - Scala 3
//> using scala 3.3.7
//> using dep com.kubuszok::hearth::0.3.0
import hearth.source.*
def exampleMethod(): Unit = {
println(summon[MethodName]) // Prints: exampleMethod
println(summon[Line]) // Prints: 42 (or whatever line this is on)
println(summon[File]) // Prints: /path/to/MyFile.scala
println(summon[FileName]) // Prints: MyFile.scala
println(summon[Location]) // Prints: /path/to/MyFile.scala:42
}
Source utilities - Scala 2
//> using scala 2.13.16
//> using dep com.kubuszok::hearth::0.3.0
import hearth.source._
def exampleMethod(): Unit = {
println(implicitly[MethodName]) // Prints: exampleMethod
println(implicitly[Line]) // Prints: 42
println(implicitly[File]) // Prints: /path/to/MyFile.scala
println(implicitly[FileName]) // Prints: MyFile.scala
println(implicitly[Location]) // Prints: /path/to/MyFile.scala:42
}
Use Cases
1. Enhanced Error Messages
Example
Add source location information to error messages for better debugging:
2. Debug Logging
Example
Include source location in debug output:
3. Automatic Diagnostics
Example
Automatically capture source context for diagnostics:
4. Location Tracking
Example
The Location type combines file and line information:
import hearth.source.*
def trackLocation[A](value: A)(implicit loc: Location): A = {
println(s"Processing value at ${loc}")
value
}
// Location also provides convenient access to fileName
def logWithFileName(message: String)(implicit loc: Location): Unit = {
println(s"[${loc.fileName}:${loc.line}] $message")
}
Understanding the Types
All source utilities use phantom types for type safety:
MethodName: A subtype ofString- useMethodName.wrap(name)to create, orsummon[MethodName]to get the current valueLine: A subtype ofInt- represents line numbers (1-based)File: A subtype ofString- full file path (normalized with forward slashes)FileName: A subtype ofString- just the filename without pathLocation: A case class containingFileandLine- can be derived implicitly if bothFileandLineare available
How It Works
Source utilities use Hearth's macro API internally to capture source location information at compile time. When you use summon[MethodName] or MethodName.derived in your code, a macro expands at that call site to capture the current source location. This is similar to how the sourcecode library works, but implemented using Hearth's utilities.
The values are determined at compile time but available at runtime, making them perfect for logging, error messages, and debugging without manual string literals.
Limitations
- Method context required:
MethodNamerequires an enclosing method (will fail in top-level code or object initialization) - File context required:
FileandFileNamerequire file position information (may fail in some REPL contexts) - Compile-time expansion: The macros expand at compile time, so the values reflect the source location where the macro is called, not where it's defined
Relationship with Other Utilities
Source utilities demonstrate how to use Hearth's macro API to build runtime utilities:
- Environment: Source utilities use
Environment.currentPositioninternally to extract location information - Better Printers: The macro implementations use Better Printers for error messages
- sourcecode library: Source utilities are a reference implementation showing how to build similar functionality using Hearth's API
If you're building your own source location utilities or need to capture source information in macros, you can use Hearth's Environment.currentPosition API directly, similar to how Source utilities do it internally.