Skip to content

ScalaMetrics is a powerful static analysis library for Scala projects. It provides comprehensive analysis at multiple granularity levels: project, package, file, method, and member.

License

Notifications You must be signed in to change notification settings

bitblends/scalametrics

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Scala Logo ScalaMetrics

The most comprehensive code metrics and code analysis library for Scala

Release Maven Central CI Scala versions License

ScalaMetrics is a powerful static analysis library for Scala projects. It provides comprehensive analysis at multiple granularity levels: project, package, file, method, and member.

Features

  • 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

Installation

Add ScalaMetrics to your build.sbt:

libraryDependencies += "com.bitblends" %% "scalametrics" % "1.1.1"

Documentation

Learn more by visiting ScalaMetrics Documentation site.

Quick Start

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.

Raw Metrics

Full project analysis (raw metrics)

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
)

Analyze a single file (with automatic dialect detection)

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)

Analyze a single file with a dialect

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
)

Aggregated Project Statistics

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]
)

Contributing

Contributions are welcome! Please see CONTRIBUTING for guidelines.

License

Licensed under the MIT License. See LICENSE file for details.

Acknowledgments

Built with: