Fix reflective structural type access warning `ManagedResources` re-implemented `Using` [1] that has been in core since 2.13. We can now make use of it as we previously bumped Scala to 2.13. Fixes the following warning: [warn] /home/darius/dev/gerritforge/analytics/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/ManagedResources.scala:22:16: reflective access of structural type member method close should be enabled [warn] by making the implicit value scala.language.reflectiveCalls visible. [warn] ---- [warn] This can be achieved by adding the import clause 'import scala.language.reflectiveCalls' [warn] or by setting the compiler option -language:reflectiveCalls. [warn] See the Scaladoc for value scala.language.reflectiveCalls for a discussion [warn] why the feature should be explicitly enabled. [warn] resource.close() [warn] ^ [1] https://www.scala-lang.org/api/2.13.10/scala/util/Using$.html Change-Id: If0ec4d5a47d254a8b51ca0ae324cc352279cf65b
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala index d3adb33..880c5e1 100644 --- a/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala +++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala
@@ -24,6 +24,8 @@ import com.googlesource.gerrit.plugins.analytics.common._ import org.kohsuke.args4j.{Option => ArgOption} +import scala.util.Using + @CommandMetaData(name = "contributors", description = "Extracts the list of contributors to a project") class ContributorsCommand @Inject()(val executor: ContributorsService, val projects: ProjectsCollection, @@ -139,7 +141,7 @@ aggregationStrategy: AggregationStrategy, extractBranches: Boolean) : TraversableOnce[UserActivitySummary] = { - ManagedResource.use(repoManager.openRepository(projectRes.getNameKey)) { repo => + Using.resource(repoManager.openRepository(projectRes.getNameKey)) { repo => val stats = new Statistics(projectRes.getNameKey, commitsStatisticsCache) val branchesExtractor = extractBranches.option(new BranchesExtractor(repo))
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractor.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractor.scala index de45f80..1725835 100644 --- a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractor.scala +++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/BranchesExtractor.scala
@@ -14,28 +14,27 @@ package com.googlesource.gerrit.plugins.analytics.common -import com.googlesource.gerrit.plugins.analytics.common.ManagedResource.use import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.{Constants, ObjectId, Repository} import org.eclipse.jgit.revwalk.RevWalk import scala.jdk.CollectionConverters._ +import scala.util.Using case class BranchesExtractor(repo: Repository) { lazy val branchesOfCommit: Map[ObjectId, Set[String]] = { - use(new Git(repo)) { git => + Using.resources(new Git(repo), new RevWalk(repo)) { (git, rw) => git.branchList.call.asScala.foldLeft(Map.empty[ObjectId, Set[String]]) { (branchesAcc, ref) => val branchName = ref.getName.drop(Constants.R_HEADS.length) - use(new RevWalk(repo)) { rw: RevWalk => - rw.markStart(rw.parseCommit(ref.getObjectId)) - rw.asScala.foldLeft(branchesAcc) { (thisBranchAcc, rev) => - val sha1 = rev.getId - thisBranchAcc.get(sha1) match { - case Some(set) => thisBranchAcc + (sha1 -> (set + branchName)) - case None => thisBranchAcc + (sha1 -> Set(branchName)) - } + rw.reset() + rw.markStart(rw.parseCommit(ref.getObjectId)) + rw.asScala.foldLeft(branchesAcc) { (thisBranchAcc, rev) => + val sha1 = rev.getId + thisBranchAcc.get(sha1) match { + case Some(set) => thisBranchAcc + (sha1 -> (set + branchName)) + case None => thisBranchAcc + (sha1 -> Set(branchName)) } } }
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatisticsLoader.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatisticsLoader.scala index 782eb44..e4dbe11 100644 --- a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatisticsLoader.scala +++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatisticsLoader.scala
@@ -21,7 +21,6 @@ import com.google.gerrit.server.project.ProjectCache import com.google.inject.Inject import com.googlesource.gerrit.plugins.analytics.{AnalyticsConfig, CommitInfo, IssueInfo} -import com.googlesource.gerrit.plugins.analytics.common.ManagedResource.use import org.eclipse.jgit.diff.{DiffFormatter, RawTextComparator} import org.eclipse.jgit.revwalk.RevWalk import org.eclipse.jgit.treewalk.{CanonicalTreeParser, EmptyTreeIterator} @@ -29,6 +28,7 @@ import scala.jdk.CollectionConverters._ import scala.jdk.OptionConverters._ +import scala.util.Using import scala.util.matching.Regex class CommitsStatisticsLoader @Inject() ( @@ -52,46 +52,46 @@ info.`match`.r, Option(info.link).getOrElse(info.html))) - use(gitRepositoryManager.openRepository(nameKey)) { repo => + Using.Manager { use => + val repo = use(gitRepositoryManager.openRepository(nameKey)) // I can imagine this kind of statistics is already being available in Gerrit but couldn't understand how to access it // which Injection can be useful for this task? - use(new RevWalk(repo)) { rw => - val reader = repo.newObjectReader() - val commit = rw.parseCommit(objectId) - val commitMessage = commit.getFullMessage + val rw = use(new RevWalk(repo)) + val reader = repo.newObjectReader() + val commit = rw.parseCommit(objectId) + val commitMessage = commit.getFullMessage - val oldTree = { - // protects against initial commit - if (commit.getParentCount == 0) - new EmptyTreeIterator - else - new CanonicalTreeParser(null, reader, rw.parseCommit(commit.getParent(0).getId).getTree) - } + val oldTree = { + // protects against initial commit + if (commit.getParentCount == 0) + new EmptyTreeIterator + else + new CanonicalTreeParser(null, reader, rw.parseCommit(commit.getParent(0).getId).getTree) + } - val newTree = new CanonicalTreeParser(null, reader, commit.getTree) + val newTree = new CanonicalTreeParser(null, reader, commit.getTree) - val df = new DiffFormatter(DisabledOutputStream.INSTANCE) - df.setRepository(repo) - df.setPathFilter(ignoreFileSuffixFilter) - df.setDiffComparator(RawTextComparator.DEFAULT) - df.setDetectRenames(true) - val diffs = df.scan(oldTree, newTree).asScala + val df = new DiffFormatter(DisabledOutputStream.INSTANCE) + df.setRepository(repo) + df.setPathFilter(ignoreFileSuffixFilter) + df.setDiffComparator(RawTextComparator.DEFAULT) + df.setDetectRenames(true) + val diffs = df.scan(oldTree, newTree).asScala - val lines = (for { - diff <- diffs - edit <- df.toFileHeader(diff).toEditList.asScala - } yield Lines(edit.getEndA - edit.getBeginA, edit.getEndB - edit.getBeginB)).fold(Lines(0, 0))(_ + _) + val lines = (for { + diff <- diffs + edit <- df.toFileHeader(diff).toEditList.asScala + } yield Lines(edit.getEndA - edit.getBeginA, edit.getEndB - edit.getBeginB)).fold(Lines(0, 0))(_ + _) - val files: Set[String] = diffs.map(df.toFileHeader(_).getNewPath).toSet + val files: Set[String] = diffs.map(df.toFileHeader(_).getNewPath).toSet - val commitInfo = CommitInfo(objectId.getName, commit.getAuthorIdent.getWhen.getTime, commit.isMerge, botLikeExtractor.isBotLike(files), files) - val commitsStats = CommitsStatistics(lines.added, lines.deleted, commitInfo.merge, commitInfo.botLike, List(commitInfo), extractIssues(commitMessage, replacers).toList) + val commitInfo = CommitInfo(objectId.getName, commit.getAuthorIdent.getWhen.getTime, commit.isMerge, botLikeExtractor.isBotLike(files), files) + val commitsStats = CommitsStatistics(lines.added, lines.deleted, commitInfo.merge, commitInfo.botLike, List(commitInfo), extractIssues(commitMessage, replacers).toList) - commitsStats - } + commitsStats } - } + }.get private def extractIssues(commitMessage: String, replacers: Seq[Replacer]): Seq[IssueInfo] = replacers.flatMap {
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/JsonStreamedResultBuilder.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/JsonStreamedResultBuilder.scala index 004259e..de01b79 100644 --- a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/JsonStreamedResultBuilder.scala +++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/JsonStreamedResultBuilder.scala
@@ -18,8 +18,10 @@ import com.google.gerrit.extensions.restapi.BinaryResult +import scala.util.Using + class GsonStreamedResult[T](val jsonFmt: GsonFormatter, val committers: TraversableOnce[T]) extends BinaryResult { override def writeTo(os: OutputStream) = - ManagedResource.use(new PrintWriter(os))(jsonFmt.format(committers, _)) + Using.resource(new PrintWriter(os))(jsonFmt.format(committers, _)) }
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/ManagedResources.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/ManagedResources.scala deleted file mode 100644 index 5cf2b74..0000000 --- a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/ManagedResources.scala +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.googlesource.gerrit.plugins.analytics.common - -object ManagedResource { - def use[A <: { def close(): Unit }, B](resource: A)(code: A ⇒ B): B = - try - code(resource) - finally - resource.close() -}