mirror of
https://github.com/sbroenne/mcp-server-excel.git
synced 2026-09-19 07:53:08 +08:00
352b1da895
Reverts the scratch verification commit; confirms PAT push authentication and ruleset bypass work end-to-end for the release-automation fix.
125 lines
4.5 KiB
PowerShell
125 lines
4.5 KiB
PowerShell
#!/usr/bin/env pwsh
|
|
<#
|
|
.SYNOPSIS
|
|
Checks that all ((dynamic)) casts in ExcelMcp.Core and ExcelMcp.ComInterop have justification comments.
|
|
|
|
.DESCRIPTION
|
|
Every use of ((dynamic)) cast (explicit type coercion) must be preceded by a comment explaining
|
|
why the PIA type cannot be used. Bare ((dynamic)) casts indicate potential PIA coverage gaps
|
|
that weren't investigated.
|
|
|
|
Valid comment prefixes (on the line immediately before the cast):
|
|
// PIA gap: ... — Type not in v16 Microsoft.Office.Interop.Excel PIA
|
|
// TODO: ... — Type IS in PIA but migration not yet done (tracked for removal)
|
|
// Reason: ... — Other documented reason for dynamic cast
|
|
|
|
False positives are excluded:
|
|
- ExcelBatch.cs / ExcelSession.cs / ExcelShutdownService.cs (infrastructure — uses `dynamic excel`)
|
|
- Lines inside comments
|
|
|
|
.EXAMPLE
|
|
.\check-dynamic-casts.ps1
|
|
|
|
.NOTES
|
|
Run automatically as part of pre-commit hook.
|
|
To add a new documented cast, place a comment ending in "// PIA gap:", "// TODO:", or "// Reason:"
|
|
on the line immediately before the ((dynamic)) cast.
|
|
#>
|
|
|
|
param(
|
|
[switch]$Verbose
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$rootDir = Split-Path -Parent $PSScriptRoot
|
|
|
|
$searchDirs = @(
|
|
(Join-Path $rootDir "src\ExcelMcp.Core"),
|
|
(Join-Path $rootDir "src\ExcelMcp.ComInterop")
|
|
)
|
|
|
|
# Files where bare dynamic casts are acceptable (infrastructure files)
|
|
$excludeFiles = @(
|
|
"ExcelBatch.cs",
|
|
"ExcelSession.cs",
|
|
"ExcelShutdownService.cs",
|
|
"ExcelShutdownHelper.cs"
|
|
)
|
|
|
|
$violations = @()
|
|
$checkedFiles = 0
|
|
|
|
foreach ($dir in $searchDirs) {
|
|
$csFiles = Get-ChildItem -Path $dir -Filter "*.cs" -Recurse -ErrorAction SilentlyContinue
|
|
foreach ($file in $csFiles) {
|
|
if ($excludeFiles -contains $file.Name) {
|
|
if ($Verbose) { Write-Host " Skipped (infrastructure): $($file.Name)" -ForegroundColor Gray }
|
|
continue
|
|
}
|
|
|
|
$checkedFiles++
|
|
$lines = Get-Content $file.FullName
|
|
for ($i = 0; $i -lt $lines.Count; $i++) {
|
|
$line = $lines[$i]
|
|
|
|
# Check for ((dynamic)) cast pattern
|
|
if ($line -match '\(\(dynamic\)') {
|
|
# Skip lines that are themselves comments
|
|
$trimmed = $line.TrimStart()
|
|
if ($trimmed.StartsWith("//")) { continue }
|
|
|
|
# Check if any preceding comment line (within 5 lines) has a justification comment
|
|
$hasJustification = $false
|
|
for ($j = $i - 1; $j -ge 0 -and $j -ge ($i - 5); $j--) {
|
|
$prevLine = $lines[$j].TrimStart()
|
|
if ([string]::IsNullOrWhiteSpace($prevLine)) { continue }
|
|
|
|
# Once we hit a non-comment line, stop looking
|
|
if (-not $prevLine.StartsWith("//")) { break }
|
|
|
|
if ($prevLine.StartsWith("// PIA gap:") -or
|
|
$prevLine.StartsWith("// TODO:") -or
|
|
$prevLine.StartsWith("// Reason:") -or
|
|
$prevLine.StartsWith("// REASON:")) {
|
|
$hasJustification = $true
|
|
break
|
|
}
|
|
}
|
|
|
|
if (-not $hasJustification) {
|
|
$violations += [PSCustomObject]@{
|
|
File = $file.FullName.Replace($rootDir, "").TrimStart("\")
|
|
Line = $i + 1
|
|
Code = $line.Trim()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Host "Checked $checkedFiles C# files for undocumented ((dynamic)) casts" -ForegroundColor Cyan
|
|
|
|
if ($violations.Count -eq 0) {
|
|
Write-Host "All ((dynamic)) casts are documented" -ForegroundColor Green
|
|
exit 0
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "UNDOCUMENTED ((dynamic)) CASTS FOUND: $($violations.Count)" -ForegroundColor Red
|
|
Write-Host ""
|
|
Write-Host "Every ((dynamic)) cast must have a comment on the preceding line explaining why:" -ForegroundColor Yellow
|
|
Write-Host ' // PIA gap: <type> not in the referenced Excel PIA because...' -ForegroundColor Gray
|
|
Write-Host ' // TODO: <type> IS in PIA, migration tracked - left as dynamic temporarily' -ForegroundColor Gray
|
|
Write-Host ' // Reason: <explanation>' -ForegroundColor Gray
|
|
Write-Host ""
|
|
|
|
foreach ($v in $violations) {
|
|
Write-Host " $($v.File):$($v.Line)" -ForegroundColor Yellow
|
|
Write-Host " $($v.Code)" -ForegroundColor Gray
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Fix these before committing. See docs/PIA-COVERAGE.md for guidance." -ForegroundColor Red
|
|
exit 1
|