microsoft / microsoft/CSS-Exchange
Add a formatter check to disallow backtick line continuation
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 (.build/Invoke-CodeFormatterOnFiles.ps1) has no check that flags backtick (`) line continuation in .ps1 / .psm1 files. Backtick continuation is a well-known PowerShell anti-pattern — trailing whitespace after the backtick silently breaks the continuation, and the character is easy to miss in review. Splatting, breaking after a pipe (|), or breaking inside an open paren / brace is preferred in every case.
Neither PSSA (as configured in PSScriptAnalyzerSettings.psd1) nor any of the existing CodeFormatterChecks/ files (CheckContainsCurlyQuotes, CheckFileHasNewlineAtEndOfFile, CheckMarkdownFileHasNoBOM, CheckMultipleEmptyLines, CheckScriptFileHasBOM, CheckScriptFileHasComplianceHeader, CheckScriptFormat, CheckTokenTypeCasing) target backtick continuation. PSAvoidUsingBackticks is not a built-in PSSA rule (it lives in the community CommunityAnalyzerRules module) and is not referenced anywhere in this repo.
Evidence
Discovered while reviewing PR #2571.
Transport/Get-TerrlExternalRecipientEstimate.ps1— 9 backtick continuations (lines 316–319, 830–833, 879).Transport/Tests/Get-TerrlExternalRecipientEstimate.Tests.ps1— 39 backtick continuations.
Every occurrence in the PR is either a cmdlet call that would be more readable as a splat, or an expression that could break naturally after | / (. Example:
# Before (line 316)
} elseif (Test-TerrlExchangeOnlineJournalReport `
-SenderAddress $senderAddress `
-Recipient $recipient `
-JournalSet $journalSet `
-JournalSenderSet $journalSenderSet) {
# After (splat)
$journalArgs = @{
SenderAddress = $senderAddress
Recipient = $recipient
JournalSet = $journalSet
JournalSenderSet = $journalSenderSet
}
} elseif (Test-TerrlExchangeOnlineJournalReport @journalArgs) {
Proposed change
Add a new CheckBacktickLineContinuation.ps1 under .build/CodeFormatterChecks/ and wire it into .build/Invoke-CodeFormatterOnFiles.ps1:
$errorCount += (CheckBacktickLineContinuation $fileInfo $Save) ? 1 : 0
Detection strategy: tokenize with [System.Management.Automation.PSParser]::Tokenize (already used by CheckTokenTypeCasing) and flag any LineContinuation token, OR match the regex `\s*$ on non-blank source lines that are outside here-strings, comments, and string literals (token stream is safer than the regex — regex would produce false positives inside single-line here-strings or ` characters inside strings).
Reporting: each occurrence should be reported with file + 1-based line number so contributors can locate them quickly.
-Save behavior: none. Auto-fixing backticks to splats is not safe (requires choosing splat variable names, deciding on placement), so this check should be report-only and let the author refactor by hand.
Acceptance criteria
-
CheckBacktickLineContinuation.ps1exists and is dot-sourced byInvoke-CodeFormatterOnFiles.ps1. -
Invoke-CodeFormatterOnFilescalls it for each file and increments$errorCounton hits. - Running against a repro script containing a backtick continuation returns a non-zero error count and prints file + line number.
- Backticks inside strings, here-strings (
@" ... "@,@' ... '@), and comments do not trigger the check. - Escaped characters that legitimately use backticks in strings (
"`t","`n","`$var") are not flagged. -
-Saveis a no-op for this check (auto-rewrite is not attempted). - A follow-up sweep PR (or PRs, if scope requires) removes existing offenders across
Admin/,Diagnostics/,Shared/,Transport/,Setup/, and theTests/folders.
Non-goals
- Auto-fix. Refactoring backtick continuations into splats or natural pipe/paren breaks is an authoring decision, not a formatter transformation.
- Blocking backticks in interactive PowerShell examples inside
docs/markdown files. - Adding the
CommunityAnalyzerRulesmodule as a formatter dependency.
Repro
@'
Get-ChildItem -Path C:\Temp `
-Recurse `
-Filter *.log
'@ | Set-Content -Path .\repro.ps1 -Encoding utf8BOM
. .build\Invoke-CodeFormatterOnFiles.ps1
Invoke-CodeFormatterOnFiles -FilePaths .\repro.ps1 # currently returns 0 errors
Related
- #2572 — Type-token casing check (drafted alongside this one from PR #2571 review).
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/Invoke-CodeFormatterOnFiles.ps1 and the existing .build/CodeFormatterChecks/ files, especially CheckTokenTypeCasing, to follow the formatter check pattern. Run the provided repro script through Invoke-CodeFormatterOnFiles and verify the new check reports each real continuation with its file and line number, ignores strings, here-strings, and comments, and leaves files unchanged with -Save.
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
- 72/100