The most comprehensive code metrics and code analysis library for Scala
ScalaMetrics is a powerful static analysis library for Scala projects. It provides comprehensive analysis at multiple granularity levels: project, package, file, method, and member.
- Multi-Level Analysis: Extract metrics at project, package, file, method, and member levels
- Comprehensive Metrics:
- Cyclomatic complexity
- Nesting depth
- Expression branch density
- Pattern matching
- Lines of code
- Documentation coverage
- Parameter and arity (implicit, using, default, varargs)
- Return type explicitness
- Inline and implicit usage
- Raw and Aggregated Metrics: Provides both raw and aggregated metrics for detailed insights
- Multiple Dialect Support: Supports Scala 2.12, 2.13, and 3
- Immutable Design: Functional pipeline architecture with immutable data flow
- ScalaMeta-Powered: Leverages ScalaMeta for accurate AST parsing and traversal
- Automatic Dialect Detection: Automatically detects Scala dialects for accurate parsing using a combination of heuristics and statistical methods
Add ScalaMetrics to your build.sbt:
libraryDependencies += "com.bitblends" %% "scalametrics" % "1.1.1"Learn more by visiting ScalaMetrics Documentation site.
ScalaMetrics offers a wide range of code metrics to help you analyze and improve the quality of your Scala codebase.
There are two types of metrics that ScalaMetrics is able to generate: Aggregated Project Statistics and Raw Metrics.
Tip
Aggregated stats are generally recommended for most use cases to begin with. Since it already includes roll-ups at various levels (project, package, file, method, member), it provides a complete overview of the project out of the box. With that said, if you need raw metrics for custom processing or analysis, use the raw metrics API.
After calling either generateProjectStats or generateProjectMetrics, you will receive a case class containing
the aggregated stats/raw metrics. You can then process these metrics based on your needs.
import java.io.File
import com.bitblends.scalametrics.metrics.model.{ProjectInfo, ProjectMetrics}
import com.bitblends.scalametrics.utils.Id
import com.bitblends.scalametrics.ScalaMetrics
// Minimal ProjectInfo setup
val projectInfo = ProjectInfo(
projectId = Id.of("MyScalaProject"), // or any unique identifier of your choice
name = "MyScalaProject",
version = "1.0.0",
scalaVersion = "2.13.17"
)
// Specify one or more source directories
val sourceDirectories = Seq(
new File("src/main/scala"),
new File("src/main/scala-3")
)
// Gather all Scala source files
val sourceFiles = sourceDirectories.flatMap { dir => (dir ** "*.scala").get }
// Generate metrics
val projectMetrics: ProjectMetrics = ScalaMetrics.generateProjectMetrics(
files = sourceFiles,
projectBaseDir = new File("/home/projects", "MyScalaProject"), // root directory of the project, example: /home/projects/MyScalaProject
projectInfo = projectInfo
)You can analyze a single Scala file to get its metrics using generateFileMetrics. The dialect will be automatically
detected based on the file content.
import java.io.File
import com.bitblends.scalametrics.ScalaMetrics
import com.bitblends.scalametrics.metrics.model.FileMetrics
val file = new File("src/main/scala/example/MyClass.scala")
val result: Option[FileMetrics] = ScalaMetrics.generateFileMetrics(file)You can also specify a dialect explicitly if you want to override the automatic detection.
import java.io.File
import com.bitblends.scalametrics.ScalaMetrics
import com.bitblends.scalametrics.metrics.model.FileMetrics
import scala.meta.Dialect
val file = new File("src/main/scala/example/MyClass.scala")
val result: Option[FileMetrics] = ScalaMetrics.generateFileMetrics(file)
// You can provide a dialect if you want to override the automatic detection
import org.scalameta.dialects.{Scala213, Scala212, Scala3}
val dialect: Dialect = Scala213 // or Scala212, Scala3
val result: Option[FileMetrics] = ScalaMetrics.generateFileMetrics(file, dialect = Some(dialect))ProjectMetrics case class contains raw metrics for the entire project, including file-level, member-level, and
method-level metrics (no package or roll-ups). FileMetrics case class contains the metrics for a single file
along with its methods and members.
case class ProjectMetrics(
projectInfo: ProjectInfo,
fileMetrics: Vector[FileMetrics]
)
case class FileMetrics(
metadata: FileMetadata,
methodMetrics: Vector[MethodMetrics] = Vector.empty,
memberMetrics: Vector[MemberMetrics] = Vector.empty
)For a complete project analysis you can provide a minimal ProjectInfo case class, source files, and the base directory
of the project to receive a ProjectStats case class.
This case class contains aggregated statistics for the entire project, including file-level, package-level, and method
and member-level statistics (with roll-ups).
import java.io.File
import com.bitblends.scalametrics.metrics.model.{ProjectInfo, ProjectStats}
import com.bitblends.scalametrics.utils.Id
import com.bitblends.scalametrics.ScalaMetrics
// Minimal ProjectInfo setup
val projectInfo = ProjectInfo(
projectId = Id.of("MyScalaProject"), // or any unique identifier of your choice
name = "MyScalaProject",
version = "1.0.0",
scalaVersion = "2.13.17"
)
// Specify one or more source directories
val sourceDirectories = Seq(
new File("src/main/scala"),
new File("src/main/scala-3")
)
// Gather all Scala source files
val sourceFiles = sourceDirectories.flatMap { dir => (dir ** "*.scala").get }
// Generate ProjectStats
val projectStats: ProjectStats = ScalaMetrics.generateProjectStats(
files = sourceFiles,
projectBaseDir = new File("/home/projects", "MyScalaProject"), // root directory of the project, example: /home/projects/MyScalaProject
projectInfo = projectInfo
)ProjectStats case class contains aggregated statistics for the entire project, including file-level, package-level,
and method and member-level statistics (with roll-ups).
case class ProjectStats(
metadata: ProjectMetadata,
rollup: Rollup,
packageStats: Vector[PackageStats]
)
// ... Rollup, ProjectMetadata (see documentation)
case class PackageStats(metadata: PackageMetadata,
rollup: Rollup,
fileStats: Vector[FileStats]
)
case class FileStats(
metadata: FileStatsMetadata,
rollup: Rollup,
memberStats: Vector[MemberStats],
methodStats: Vector[MethodStats]
)Contributions are welcome! Please see CONTRIBUTING for guidelines.
Licensed under the MIT License. See LICENSE file for details.
Built with:
- ScalaMeta - Scala metaprogramming library