sbt.inc.APIDiff.scala Maven / Gradle / Ivy
package sbt.inc
import xsbti.api.SourceAPI
import xsbt.api.ShowAPI
import xsbt.api.DefaultShowAPI._
import java.lang.reflect.Method
import java.util.{List => JList}
/**
* A class which computes diffs (unified diffs) between two textual representations of an API.
*
* Internally, it uses java-diff-utils library but it calls it through reflection so there's
* no hard dependency on java-diff-utils.
*
* The reflective lookup of java-diff-utils library is performed in the constructor. Exceptions
* thrown by reflection are passed as-is to the caller of the constructor.
*
* @throws ClassNotFoundException if difflib.DiffUtils class cannot be located
* @throws LinkageError
* @throws ExceptionInInitializerError
*/
private[inc] class APIDiff {
import APIDiff._
private val diffUtilsClass = Class.forName(diffUtilsClassName)
// method signature: diff(List>, List>)
private val diffMethod: Method =
diffUtilsClass.getMethod(diffMethodName, classOf[JList[_]], classOf[JList[_]])
private val generateUnifiedDiffMethod: Method = {
val patchClass = Class.forName(patchClassName)
// method signature: generateUnifiedDiff(String, String, List, Patch, int)
diffUtilsClass.getMethod(generateUnifiedDiffMethodName, classOf[String],
classOf[String], classOf[JList[String]], patchClass, classOf[Int])
}
/**
* Generates an unified diff between textual representations of `api1` and `api2`.
*/
def generateApiDiff(fileName: String, api1: SourceAPI, api2: SourceAPI, contextSize: Int): String = {
val api1Str = ShowAPI.show(api1)
val api2Str = ShowAPI.show(api2)
generateApiDiff(fileName, api1Str, api2Str, contextSize)
}
private def generateApiDiff(fileName: String, f1: String, f2: String, contextSize: Int): String = {
assert((diffMethod != null) && (generateUnifiedDiffMethod != null), "APIDiff isn't properly initialized.")
import scala.collection.JavaConverters._
def asJavaList[T](it: Iterator[T]): java.util.List[T] = it.toSeq.asJava
val f1Lines = asJavaList(f1.lines)
val f2Lines = asJavaList(f2.lines)
//val diff = DiffUtils.diff(f1Lines, f2Lines)
val diff /*: Patch*/ = diffMethod.invoke(null, f1Lines, f2Lines)
val unifiedPatch: JList[String] = generateUnifiedDiffMethod.invoke(null, fileName, fileName, f1Lines, diff,
(contextSize: java.lang.Integer)).asInstanceOf[JList[String]]
unifiedPatch.asScala.mkString("\n")
}
}
private[inc] object APIDiff {
private val diffUtilsClassName = "difflib.DiffUtils"
private val patchClassName = "difflib.Patch"
private val diffMethodName = "diff"
private val generateUnifiedDiffMethodName = "generateUnifiedDiff"
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy