Custom PSScriptAnalyzerRule - Function Capitalization
I’ve got a number of custom PSScriptAnalyzer rules that I sometimes run. A little while ago I uploaded them to GitHub to share with others. Today I’m going to walk you through the AvoidImproperlyCapitalizedFunctionNames rule I wrote.
I wrote documentation (and tests) for these with the intention of someday making a pull request to PSSA to add these rules, but PSSA is not currently set up to include script-based rules. Here’s the description of my rule, from the documentation I wrote.
According to the PowerShell Practice and Style guide's section on capitalization conventions (community developed, but referencse Microsoft's published document on the same for the .NET framework), it is best practice to use PascalCase for functions inside of modules and scripts. This means that that one should never see adjacent capital letters in a Function name. An exception exists for two letter acronyms only like "VM" for Virtual Machine or "PS" for PowerShell (ex:Get-PSDrive
). This should not extend to compound acronyms like Azure Resource manager's "RM" meets Virtual Machine "VM" inStart-AzureRmVM
. Accordingly, this rule warns on instances where four or more adjacent capital letters are found in a function name.
With this description, it’s no surprise that my rule will identify functions with 4 or more adjacent capital letters. It’s not a perfect solution, because people could still implement things in all lowercase, or with other improperly capitalized names, but it’s a good start.
function Test-FunctionCasing {
[CmdletBinding()]
[OutputType([PSCustomObject[]])]
param (
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Language.ScriptBlockAst]$ScriptBlockAst
)
process {
try {
$functions = $ScriptBlockAst.FindAll( { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] -and
$args[0].Name -cmatch '[A-Z]{4,}' }, $true )
foreach ( $function in $functions )
{
[PSCustomObject]@{
Message = 'Avoid function names with more than 3 capital letters in a row in their name'
Extent = $function.Extent
RuleName = 'PSAvoidImproperlyCapitalizedFunctionNames'
Severity = 'Warning'
}
}
}
catch {
$PSCmdlet.ThrowTerminatingError( $_ )
}
}
}
Custom PSSA rules need to take some sort of AST object, and mine takes a ScriptBlockAST so it can go through all the declared functions in that AST. Line 12 will get all the function definitions with names that have 4 or more adjacent capital letters. For each of those, I return a PSSA warning about violating the naming convention.