|
| 1 | +package dotty.tools |
| 2 | +package dotc |
| 3 | +package reporting |
| 4 | + |
| 5 | +import core.* |
| 6 | +import Contexts.{Context, ctx} |
| 7 | +import collection.mutable |
| 8 | +import util.{EqHashMap, NoSourcePosition} |
| 9 | + |
| 10 | +abstract class Profile: |
| 11 | + def unitProfile(unit: CompilationUnit): Profile.Info |
| 12 | + def recordNewLine()(using Context): Unit |
| 13 | + def recordNewToken()(using Context): Unit |
| 14 | + def recordTasty(size: Int)(using Context): Unit |
| 15 | + def printSummary()(using Context): Unit |
| 16 | + |
| 17 | +object Profile: |
| 18 | + def current(using Context): Profile = |
| 19 | + if ctx.run == null then NoProfile else ctx.run.profile |
| 20 | + |
| 21 | + private val TastyFactor = 40 |
| 22 | + |
| 23 | + class Info: |
| 24 | + var lineCount: Int = 0 |
| 25 | + var tokenCount: Int = 0 |
| 26 | + var tastySize: Int = 0 |
| 27 | + def complexity: Float = tastySize.toFloat/lineCount/TastyFactor |
| 28 | +end Profile |
| 29 | + |
| 30 | +class ActiveProfile extends Profile: |
| 31 | + |
| 32 | + private val pinfo = new EqHashMap[CompilationUnit, Profile.Info] |
| 33 | + |
| 34 | + private val junkInfo = new Profile.Info |
| 35 | + |
| 36 | + private def curInfo(using Context): Profile.Info = |
| 37 | + val unit = ctx.compilationUnit |
| 38 | + if unit == null then junkInfo else unitProfile(unit) |
| 39 | + |
| 40 | + def unitProfile(unit: CompilationUnit): Profile.Info = |
| 41 | + pinfo.getOrElseUpdate(unit, new Profile.Info) |
| 42 | + |
| 43 | + def recordNewLine()(using Context): Unit = |
| 44 | + curInfo.lineCount += 1 |
| 45 | + def recordNewToken()(using Context): Unit = |
| 46 | + curInfo.tokenCount += 1 |
| 47 | + def recordTasty(size: Int)(using Context): Unit = |
| 48 | + curInfo.tastySize += size |
| 49 | + |
| 50 | + def printSummary()(using Context): Unit = |
| 51 | + val units = |
| 52 | + val rawUnits = pinfo.keysIterator.toArray |
| 53 | + ctx.settings.YprofileSortedBy.value match |
| 54 | + case "name" => rawUnits.sortBy(_.source.file.name) |
| 55 | + case "path" => rawUnits.sortBy(_.source.file.path) |
| 56 | + case "lines" => rawUnits.sortBy(unitProfile(_).lineCount) |
| 57 | + case "tokens" => rawUnits.sortBy(unitProfile(_).tokenCount) |
| 58 | + case "complexity" => rawUnits.sortBy(unitProfile(_).complexity) |
| 59 | + case _ => rawUnits.sortBy(unitProfile(_).tastySize) |
| 60 | + |
| 61 | + val nameWidth = units.map(_.source.file.name.length).max.max(10).min(50) |
| 62 | + val layout = s"%-${nameWidth}s %6s %8s %8s %s %s" |
| 63 | + report.echo(layout.format("Source file", "Lines", "Tokens", "Tasty", " Complexity/Line", "Directory")) |
| 64 | + |
| 65 | + def printInfo(name: String, info: Profile.Info, path: String) = |
| 66 | + val complexity = info.complexity |
| 67 | + val explanation = |
| 68 | + if complexity < 1 then "low " |
| 69 | + else if complexity < 5 then "moderate" |
| 70 | + else if complexity < 25 then "high " |
| 71 | + else "extreme " |
| 72 | + val complexityStr = s"${"%6.2f".format(info.complexity)} $explanation" |
| 73 | + report.echo(layout.format( |
| 74 | + name, info.lineCount, info.tokenCount, info.tastySize, complexityStr, path)) |
| 75 | + |
| 76 | + val agg = new Profile.Info |
| 77 | + for unit <- units do |
| 78 | + val info = unitProfile(unit) |
| 79 | + val file = unit.source.file |
| 80 | + printInfo(file.name, info, file.container.path) |
| 81 | + agg.lineCount += info.lineCount |
| 82 | + agg.tokenCount += info.tokenCount |
| 83 | + agg.tastySize += info.tastySize |
| 84 | + if units.length > 1 then |
| 85 | + report.echo(s"${"-"*nameWidth}------------------------------------------") |
| 86 | + printInfo("Total", agg, "") |
| 87 | + end printSummary |
| 88 | +end ActiveProfile |
| 89 | + |
| 90 | +object NoProfile extends Profile: |
| 91 | + def unitProfile(unit: CompilationUnit) = unsupported("NoProfile.info") |
| 92 | + def recordNewLine()(using Context): Unit = () |
| 93 | + def recordNewToken()(using Context): Unit = () |
| 94 | + def recordTasty(size: Int)(using Context): Unit = () |
| 95 | + def printSummary()(using Context): Unit = () |
0 commit comments