microsoft / microsoft/CSS-Exchange
Extend CheckTokenTypeCasing to enforce lowercase Type token casing
Nobody has claimed this yet.
- Dominant language
- PowerShell
- Stars
- 1.3k
- Forks
- 395
- Avg merge
- 14h 7m
- Merged PRs (30d)
- 5
Description
Summary
Our code formatter's CheckTokenTypeCasing check (.build/CodeFormatterChecks/CheckTokenTypeCasing.ps1) currently only inspects Operator and Keyword PowerShell token types. It does not inspect the Type token type, which means inconsistent casing of type accelerators and built-in .NET short-form names slips through the pipeline unnoticed.
Neither PSSA's PSUseCorrectCasing (as configured in PSScriptAnalyzerSettings.psd1) nor any of the other seven checks wired into Invoke-CodeFormatterOnFiles flag this either — verified by running the current settings against a file mixing [DateTime]/[datetime], [TimeSpan], [Math]/[math] (zero diagnostics).
Evidence
Discovered while reviewing PR #2571. Transport/Get-TerrlExternalRecipientEstimate.ps1 uses both spellings in the same 911-line file, and the same concept is spelled two different ways:
| Lowercase (majority) | PascalCase (nested wrapper) |
|---|---|
L100, L103, L449, L450, L497 [datetime] |
L539, L542 [DateTime] |
L387, L401 [math] |
L588 [Math] |
| — | L532 [TimeSpan], L533/L579/L595/L602 [DateTime], L453 [ScriptBlock] |
The formatter, SpellCheck.ps1, and Pester all pass, so the mixed casing merges cleanly.
Proposed change
Extend CheckTokenTypeCasing.ps1 to accept Type as a third option in the -Type ValidateSet, then wire a new call into .build/Invoke-CodeFormatterOnFiles.ps1:
$errorCount += (CheckTokenTypeCasing $fileInfo $Save "Type") ? 1 : 0
Enforcement rule: for tokens with PSTokenType.Type whose Content matches a known type accelerator or built-in short type name (datetime, timespan, string, int, bool, guid, math, scriptblock, hashtable, pscustomobject, object, convert, char, byte, long, double, decimal, regex, xml, array, void, type, etc.), require the lowercase form. Fully-qualified .NET namespaces ([System.DateTime], [System.Collections.Generic.List[object]]) should be left alone — those retain their canonical framework casing.
-Save behavior: rewrite the token in place using the same offset/insert pattern the existing Operator/Keyword branches already use.
Acceptance criteria
-
CheckTokenTypeCasing'sValidateSetincludes"Type". -
Invoke-CodeFormatterOnFilesinvokes the check with-Type Type. - Running the formatter against the reproducer (a script containing
[DateTime],[TimeSpan],[Math]) reports errors without-Saveand rewrites them to lowercase with-Save. - Fully-qualified type names (
[System.Collections.Generic.List[object]],[System.StringComparer]) are left untouched. - A follow-up sweep PR normalizes existing offenders under
Transport/,Shared/,Diagnostics/, etc.
Non-goals
- Enforcing casing on fully-qualified .NET type names (that's already handled correctly by the framework and would produce large, noisy diffs).
- Any change to
PSScriptAnalyzerSettings.psd1.
Repro
@'
[DateTime]::UtcNow
[TimeSpan]::FromMinutes(5)
[Math]::Round(1.0, 1)
'@ | Set-Content -Path .\repro.ps1 -Encoding utf8BOM
. .build\Invoke-CodeFormatterOnFiles.ps1
Invoke-CodeFormatterOnFiles -FilePaths .\repro.ps1 # currently returns 0 errors
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read .build/CodeFormatterChecks/CheckTokenTypeCasing.ps1 and .build/Invoke-CodeFormatterOnFiles.ps1, then run the supplied repro through Invoke-CodeFormatterOnFiles without -Save. Done means Type tokens are reported and lowercased with -Save, while fully qualified names remain unchanged; verify the acceptance examples and formatter output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- powershell
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100