综合平台编程器项目的远程存储
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

175 lines
6.2 KiB

  1. [CmdletBinding()]
  2. param(
  3. [Parameter()]
  4. [string]$SourcePath = (Join-Path $PSScriptRoot '..\app\src'),
  5. [Parameter()]
  6. [switch]$ShowFiles
  7. )
  8. Set-StrictMode -Version Latest
  9. $ErrorActionPreference = 'Stop'
  10. function Get-CodeLineStatistics {
  11. param(
  12. [Parameter(Mandatory)]
  13. [string]$FilePath
  14. )
  15. $statistics = [ordered]@{
  16. TotalLines = 0
  17. BlankLines = 0
  18. CommentOnlyLines = 0
  19. PreprocessorLines = 0
  20. CodeLines = 0
  21. }
  22. $inBlockComment = $false
  23. $inRawString = $false
  24. $rawStringTerminator = ''
  25. foreach ($line in [System.IO.File]::ReadLines($FilePath, [System.Text.UTF8Encoding]::new($false))) {
  26. $statistics.TotalLines++
  27. $index = 0
  28. $code = [System.Text.StringBuilder]::new()
  29. $containsComment = $inBlockComment
  30. while ($index -lt $line.Length) {
  31. if ($inRawString) {
  32. $terminatorIndex = $line.IndexOf($rawStringTerminator, $index, [System.StringComparison]::Ordinal)
  33. if ($terminatorIndex -lt 0) {
  34. [void]$code.Append($line.Substring($index))
  35. $index = $line.Length
  36. continue
  37. }
  38. [void]$code.Append($line.Substring($index, $terminatorIndex + $rawStringTerminator.Length - $index))
  39. $index = $terminatorIndex + $rawStringTerminator.Length
  40. $inRawString = $false
  41. continue
  42. }
  43. if ($inBlockComment) {
  44. $containsComment = $true
  45. $commentEnd = $line.IndexOf('*/', $index, [System.StringComparison]::Ordinal)
  46. if ($commentEnd -lt 0) {
  47. $index = $line.Length
  48. continue
  49. }
  50. $index = $commentEnd + 2
  51. $inBlockComment = $false
  52. continue
  53. }
  54. $current = $line[$index]
  55. $next = if ($index + 1 -lt $line.Length) { $line[$index + 1] } else { [char]0 }
  56. if ($current -eq '/' -and $next -eq '/') {
  57. $containsComment = $true
  58. break
  59. }
  60. if ($current -eq '/' -and $next -eq '*') {
  61. $containsComment = $true
  62. $inBlockComment = $true
  63. $index += 2
  64. continue
  65. }
  66. if ($current -eq 'R' -and $next -eq '"') {
  67. $delimiterStart = $index + 2
  68. $openParenthesis = $line.IndexOf('(', $delimiterStart)
  69. if ($openParenthesis -ge 0 -and $openParenthesis - $delimiterStart -le 16) {
  70. $delimiter = $line.Substring($delimiterStart, $openParenthesis - $delimiterStart)
  71. if ($delimiter -notmatch '[\s\\()]') {
  72. $rawStringTerminator = ')' + $delimiter + '"'
  73. [void]$code.Append($line.Substring($index, $openParenthesis - $index + 1))
  74. $index = $openParenthesis + 1
  75. $inRawString = $true
  76. continue
  77. }
  78. }
  79. }
  80. if ($current -eq '"' -or $current -eq "'") {
  81. $quote = $current
  82. [void]$code.Append($quote)
  83. $index++
  84. while ($index -lt $line.Length) {
  85. $stringCharacter = $line[$index]
  86. [void]$code.Append($stringCharacter)
  87. $index++
  88. if ($stringCharacter -eq '\\' -and $index -lt $line.Length) {
  89. [void]$code.Append($line[$index])
  90. $index++
  91. continue
  92. }
  93. if ($stringCharacter -eq $quote) {
  94. break
  95. }
  96. }
  97. continue
  98. }
  99. [void]$code.Append($current)
  100. $index++
  101. }
  102. $remaining = $code.ToString().Trim()
  103. if ([string]::IsNullOrWhiteSpace($line)) {
  104. $statistics.BlankLines++
  105. }
  106. elseif ($remaining.StartsWith('#')) {
  107. $statistics.PreprocessorLines++
  108. }
  109. elseif (-not [string]::IsNullOrWhiteSpace($remaining)) {
  110. $statistics.CodeLines++
  111. }
  112. elseif ($containsComment) {
  113. $statistics.CommentOnlyLines++
  114. }
  115. else {
  116. $statistics.BlankLines++
  117. }
  118. }
  119. return [pscustomobject]$statistics
  120. }
  121. $resolvedSourcePath = (Resolve-Path -LiteralPath $SourcePath).Path
  122. $files = Get-ChildItem -LiteralPath $resolvedSourcePath -Recurse -File -Filter '*.cpp' | Sort-Object FullName
  123. if ($files.Count -eq 0) {
  124. throw "未在 '$resolvedSourcePath' 找到 .cpp 文件"
  125. }
  126. $fileResults = foreach ($file in $files) {
  127. $statistics = Get-CodeLineStatistics -FilePath $file.FullName
  128. [pscustomobject]@{
  129. File = $file.FullName.Substring($resolvedSourcePath.Length).TrimStart('\', '/')
  130. CodeLines = $statistics.CodeLines
  131. TotalLines = $statistics.TotalLines
  132. BlankLines = $statistics.BlankLines
  133. CommentOnlyLines = $statistics.CommentOnlyLines
  134. PreprocessorLines = $statistics.PreprocessorLines
  135. }
  136. }
  137. $total = [pscustomobject]@{
  138. File = '合计'
  139. CodeLines = [int]($fileResults | Measure-Object -Property CodeLines -Sum).Sum
  140. TotalLines = [int]($fileResults | Measure-Object -Property TotalLines -Sum).Sum
  141. BlankLines = [int]($fileResults | Measure-Object -Property BlankLines -Sum).Sum
  142. CommentOnlyLines = [int]($fileResults | Measure-Object -Property CommentOnlyLines -Sum).Sum
  143. PreprocessorLines = [int]($fileResults | Measure-Object -Property PreprocessorLines -Sum).Sum
  144. }
  145. Write-Host "扫描目录: $resolvedSourcePath"
  146. Write-Host "统计范围: $($files.Count) 个 .cpp 文件,不统计 .h;移除注释及 # 预处理指令后统计代码行"
  147. Write-Host "总行数: $($total.TotalLines)"
  148. Write-Host "纯 C++ 代码: $($total.CodeLines) 行"
  149. Write-Host "空白行: $($total.BlankLines) | 纯注释行: $($total.CommentOnlyLines) | 预处理行: $($total.PreprocessorLines)"
  150. if ($ShowFiles) {
  151. $fileResults | Format-Table File, CodeLines, TotalLines, BlankLines, CommentOnlyLines, PreprocessorLines -AutoSize
  152. }