Last active
January 3, 2016 01:19
-
-
Save victorvogelpoel/8388014 to your computer and use it in GitHub Desktop.
Measure-ScriptCode (PowerShell 3+ version) calculates some metrics about the script- and module files it is fed, like number of comments, lines-of-code, number of functions, workflows and filters.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Measure-ScriptCode.ps1 | |
# Return metrics about the script and module files | |
# PowerShell 3 is required as Abstract Syntax Trees are used. | |
# Jan 2014 | |
# If this works, Victor Vogelpoel <[email protected]> wrote this. | |
# If it doesn't, I don't know who wrote this. | |
# | |
# Disclaimer | |
# This script is provided AS IS without warranty of any kind. I disclaim all implied warranties including, without limitation, | |
# any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or | |
# performance of the sample scripts and documentation remains with you. In no event shall I be liable for any damages whatsoever | |
# (including, without limitation, damages for loss of business profits, business interruption, loss of business information, | |
# or other pecuniary loss) arising out of the use of or inability to use the script or documentation. | |
#requires -version 3 | |
Set-PSDebug -Strict | |
Set-StrictMode -Version Latest | |
function Measure-ScriptCode | |
{ | |
[CmdletBinding()] | |
param | |
( | |
[Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage="One or more PS1 or PSM1 files to calculate code metrics for")] | |
[Alias('PSPath', 'Path')] | |
[string[]]$ScriptFile | |
) | |
begin | |
{ | |
$files = 0 | |
$modules = 0 | |
$manifests = 0 | |
$lines = 0 | |
$words = 0 | |
$characters = 0 | |
$codeLines = 0 | |
$comments = 0 | |
$functions = 0 | |
$workflows = 0 | |
$filters = 0 | |
$parseErrors = 0 | |
} | |
process | |
{ | |
foreach ($file in $ScriptFile) | |
{ | |
if ($file -like "*.ps1") { $files++ } | |
if ($file -like "*.psm1") { $modules++ } | |
if ($file -like "*.psd1") { $manifests++ } | |
$fileContentsArray = Get-Content -Path $file | |
if ($fileContentsArray) | |
{ | |
# First, measure basic metrics | |
$measurement = $fileContentsArray | Measure-Object -Character -IgnoreWhiteSpace -Word -Line | |
$lines += $measurement.Lines | |
$words += $measurement.Words | |
$characters += $measurement.Characters | |
$tokenAst = $null | |
$parseErrorsAst = $null | |
# Use the PowerShell 3 file parser to create the scriptblock AST, tokens and error collections | |
$scriptBlockAst = [System.Management.Automation.Language.Parser]::ParseFile($file, [ref]$tokenAst, [ref]$parseErrorsAst) | |
# Get the number of comment lines and comments on the end of a code line | |
$comments += @($tokenAst | where { $_.Kind -eq "Comment" } ).Length | |
# Calculate the 'lines of code': any line not containing comment or commentblock and not an empty or whitespace line. | |
# Remove comment tokens from the tokenAst, remove all double newlines and count all the newlines (minus 1) | |
$prevTokenIsNewline = $false | |
$codeLines += @($tokenAst | select -ExpandProperty Kind | where { $_ -ne "comment" } | where { | |
if ($_ -ne "NewLine" -or (!$prevTokenIsNewline)) | |
{ | |
$_ | |
} | |
$prevTokenIsNewline = ($_ -eq "NewLine") | |
} | where { $_ -eq "NewLine" }).Length-1 | |
$parseErrors += @($parseErrorsAst).Length | |
if ($scriptBlockAst -ne $null) | |
{ | |
# Find all functions, filters and workflows in the AST, including nested functions | |
$functionAst = $scriptBlockAst.FindAll({ $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst]}, $true) | |
# Count the specific implementation: 'function', 'filter' or 'workflow' | |
$functions += @($functionAst | where { (!$_.IsFilter) -and (!$_.IsWorkflow) }).Length | |
$filters += @($functionAst | where { $_.IsFilter }).Length | |
$workflows += @($functionAst | where { $_.IsWorkflow }).Length | |
} | |
} | |
} | |
} | |
end | |
{ | |
return [PSCustomObject]@{ | |
Files = $files | |
Modules = $modules | |
Manifests = $manifests | |
CodeLines = $codeLines | |
Comments = $comments | |
Functions = $functions | |
Workflows = $workflows | |
Filters = $filters | |
ParseErrors = $parseErrors | |
Characters = $characters | |
Lines = $lines | |
Words = $words | |
} | |
} | |
} | |
Measure-ScriptCode -ScriptFile (Join-Path $PSScriptRoot "Write-HelloWorld.ps1") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment