Add tailrec annotation

This commit is contained in:
xuwei-k 2026-01-11 16:33:45 +09:00
parent 4bee8747e9
commit c0fe4dfb10
14 changed files with 36 additions and 0 deletions

View File

@ -16,6 +16,8 @@ import sbt.util.cacheLevel
import sbt.util.CacheLevelTag
import xsbti.Attic
import scala.annotation.tailrec
trait ContextUtil[C <: Quotes & scala.Singleton](val valStart: Int):
val qctx: C
import qctx.reflect.*
@ -84,6 +86,7 @@ trait ContextUtil[C <: Quotes & scala.Singleton](val valStart: Int):
s"Input($tpe, $qual, $term, $name, $tags)"
def isCacheInput: Boolean = tags.nonEmpty
lazy val tags = extractTags(qual)
@tailrec
private def extractTags(tree: Term): List[CacheLevelTag] =
def getCacheLevelAnnotation(tree: Term): Option[Term] =
Option(tree.tpe.termSymbol) match

View File

@ -9,6 +9,8 @@
package sbt.internal.util
package complete
import scala.annotation.tailrec
object ProcessError {
def apply(command: String, msgs: Seq[String], index: Int): String = {
val (line, modIndex) = extractLine(command, index)
@ -24,6 +26,7 @@ object ProcessError {
}
def takeRightWhile(s: String)(pred: Char => Boolean): String = {
@tailrec
def loop(i: Int): String =
if (i < 0)
s

View File

@ -9,6 +9,8 @@
package sbt.internal.util
package complete
import scala.annotation.tailrec
object JLineTest {
import DefaultParsers.*
@ -33,6 +35,7 @@ object JLineTest {
val parser = parsers(args(0))
JLineCompletion.installCustomCompletor(reader, parser)
@tailrec
def loop(): Unit = {
val line = reader.readLine("> ")
if (line ne null) {

View File

@ -8,6 +8,7 @@
package sbt.internal.util
import scala.annotation.tailrec
import scala.collection.mutable.ArrayBuffer
import scala.util.Try
@ -70,6 +71,7 @@ object EscHelpers {
sb.toString
}
@tailrec
private def nextESC(s: String, start: Int, sb: java.lang.StringBuilder): Unit = {
val escIndex = s.indexOf(ESC, start)
if (escIndex < 0) {
@ -243,6 +245,7 @@ object EscHelpers {
* Skips the escape sequence starting at `i-1`. `i` should be positioned at the character after
* the ESC that starts the sequence.
*/
@tailrec
private def skipESC(s: String, i: Int): Int = {
if (i >= s.length) {
i

View File

@ -10,6 +10,8 @@ package sbt.internal.util
import sbt.util.*
import scala.annotation.tailrec
/**
* Provides a `java.io.Writer` interface to a `Logger`. Content is line-buffered and logged at
* `level`. A line is delimited by `nl`, which is by default the platform line separator.
@ -48,6 +50,7 @@ class LoggerWriter(
process()
}
@tailrec
private def process(): Unit = {
val i = buffer.indexOf(nl)
if (i >= 0) {

View File

@ -1,6 +1,8 @@
package sbt.internal.librarymanagement
package cross
import scala.annotation.tailrec
object CrossVersionUtil {
val trueString = "true"
val falseString = "false"
@ -75,6 +77,7 @@ object CrossVersionUtil {
case _ => None
}
@tailrec
private[sbt] def binaryScala3Version(full: String): String = full match {
case ReleaseV(maj, _, _, _) => maj
case NonReleaseV_n(maj, min, patch, _) if min.toLong > 0 || patch.toLong > 0 => maj

View File

@ -3,6 +3,7 @@
*/
package sbt.librarymanagement
import scala.annotation.tailrec
import scala.quoted.*
object Configurations {
@ -101,6 +102,7 @@ private[librarymanagement] abstract class ConfigurationExtra {
private[sbt] object ConfigurationMacro:
def configMacroImpl(name: Expr[String])(using Quotes): Expr[Configuration] =
import quotes.reflect.*
@tailrec
def enclosingTerm(sym: Symbol): Symbol =
sym match
case sym if sym.flags.is(Flags.Macro) => enclosingTerm(sym.owner)

View File

@ -5,6 +5,7 @@ import lmcoursier.definitions.{ Configuration, Module, ModuleName, Organization
import sbt.librarymanagement.{ CrossVersion, InclExclRule, ModuleID }
import sbt.util.Logger
import scala.annotation.tailrec
import scala.collection.mutable
object Inputs {
@ -28,6 +29,7 @@ object Inputs {
def allExtends(c: Configuration) = {
// possibly bad complexity
@tailrec
def helper(current: Set[Configuration]): Set[Configuration] = {
val newSet = current ++ current.flatMap(configs0.getOrElse(_, Nil))
if ((newSet -- current).nonEmpty)

View File

@ -34,6 +34,7 @@ object IPC {
val random = new java.util.Random
def nextPort = random.nextInt(portMax - portMin + 1) + portMin
@tailrec
def createServer(attempts: Int): ServerSocket =
if (attempts > 0) {
try new ServerSocket(nextPort, socketBacklog, loopback)

View File

@ -10,6 +10,7 @@ package sbt
package std
import java.io.File
import scala.annotation.tailrec
import scala.quoted.*
import scala.reflect.ClassTag
@ -68,6 +69,7 @@ private[sbt] object KeyMacro:
private def enclosingTerm(using qctx: Quotes) =
import qctx.reflect.*
@tailrec
def enclosingTerm0(sym: Symbol): Symbol =
sym match
case sym if sym.flags.is(Flags.Macro) => enclosingTerm0(sym.owner)
@ -77,6 +79,7 @@ private[sbt] object KeyMacro:
private def enclosingClass(using Quotes) =
import quotes.reflect.*
@tailrec
def rec(sym: Symbol): Symbol =
if sym.isClassDef then sym
else rec(sym.owner)

View File

@ -24,6 +24,8 @@ import BasicCommandStrings.*, BasicKeys.*
import sbt.internal.util.Terminal.hasConsole
import sbt.ProjectExtra.*
import scala.annotation.tailrec
private[sbt] object TemplateCommandUtil {
def templateCommand: Command = templateCommand0(TemplateCommand)
def templateCommandAlias: Command = templateCommand0("init")
@ -206,6 +208,7 @@ private[sbt] object TemplateCommandUtil {
private def toLetter(idx: Int): String =
nonMoveLetters(idx).toString
@tailrec
private def askTemplate(mappingList: List[(String, (String, String))], focus: Int): String = {
val msg = "Select a template"
displayMappings(mappingList, focus)

View File

@ -19,6 +19,7 @@ import sbt.internal.util.*
import sbt.internal.client.NetworkClient
import sbt.std.Transform.DummyTaskMap
import sbt.util.{ Logger, Show }
import scala.annotation.tailrec
sealed trait Aggregation
object Aggregation {
@ -249,6 +250,7 @@ object Aggregation {
extra: BuildUtil[Proj],
): Iterable[ScopedKey[?]] =
val mask = ScopeMask()
@tailrec
def recur(keys: Set[ScopedKey[?]], acc: Set[ScopedKey[?]]): Set[ScopedKey[?]] =
if keys.isEmpty then acc
else

View File

@ -22,6 +22,7 @@ import sbt.ProjectExtra.{ extract, setProject }
import sbt.SlashSyntax0.*
import sbt.io.{ Hash, IO }
import scala.annotation.tailrec
object Script {
final val Name = "script"
@ -79,6 +80,7 @@ object Script {
final case class Block(offset: Int, lines: Seq[String])
def blocks(file: File): Seq[Block] = {
val lines = IO.readLines(file).toIndexedSeq
@tailrec
def blocks(b: Block, acc: List[Block]): List[Block] =
if (b.lines.isEmpty) acc.reverse
else {

View File

@ -12,6 +12,8 @@ import org.scalacheck.*
import Prop.*
import TaskGen.*
import scala.annotation.tailrec
object TaskRunnerCallTest extends Properties("TaskRunner Call") {
property("calculates fibonacci") = forAll(MaxTasksGen, MaxWorkersGen) { (i: Int, workers: Int) =>
(i > 0) ==> {
@ -36,6 +38,7 @@ object TaskRunnerCallTest extends Properties("TaskRunner Call") {
}
final def fibDirect(i: Int): Int = {
require(i > 0)
@tailrec
def build(index: Int, x1: Int, x2: Int): Int =
if (index == i)
x2