Skip to content

Commit 4937354

Browse files
committed
feat(脚本管理): 增强shim生成功能以支持参数和帮助信息
解析源脚本的元数据(Help, Param, CmdletBinding)并集成到生成的shim中 支持参数绑定和帮助信息透传,提升脚本调用的兼容性
1 parent e19e445 commit 4937354

1 file changed

Lines changed: 82 additions & 16 deletions

File tree

‎Manage-BinScripts.ps1‎

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -88,24 +88,90 @@ function Sync-BinScripts {
8888
# 构建源文件的相对路径 (假设 bin 和 scripts 都在项目根目录下)
8989
$sourceRelPath = Join-Path '..' (Join-Path 'scripts' (Join-Path 'pwsh' $relativePath))
9090

91-
# 生成 Shim 内容
92-
$shimContent = @(
93-
"#!/usr/bin/env pwsh",
94-
"",
95-
"# Auto-generated shim by Manage-BinScripts.ps1",
96-
"# Source: $($script.FullName)",
97-
"",
98-
"`$SourcePath = Join-Path `$PSScriptRoot '$sourceRelPath'",
99-
"if (-not (Test-Path `$SourcePath)) {",
100-
" Write-Error ""Cannot find source script at `$SourcePath""",
101-
" exit 1",
102-
"}",
103-
"& `$SourcePath @args",
104-
"exit `$LASTEXITCODE"
105-
)
91+
# --- 解析源脚本元数据 (Help, Param, CmdletBinding) ---
92+
$sourceContent = Get-Content -Path $script.FullName -Raw
93+
$tokens = $null
94+
$errors = $null
95+
$ast = [System.Management.Automation.Language.Parser]::ParseInput($sourceContent, [ref]$tokens, [ref]$errors)
96+
97+
$paramBlockText = $null
98+
$helpText = $null
99+
$hasCmdletBinding = $false
100+
101+
# 1. 提取 ParamBlock
102+
if ($ast.ParamBlock) {
103+
$paramBlockText = $ast.ParamBlock.Extent.Text
104+
105+
# 检查是否有 CmdletBinding
106+
foreach ($attr in $ast.ParamBlock.Attributes) {
107+
if ($attr.TypeName.FullName -match 'CmdletBinding') {
108+
$hasCmdletBinding = $true
109+
# 尝试获取完整的 CmdletBinding 定义 (包括参数)
110+
$cmdletBindingText = $attr.Extent.Text
111+
break
112+
}
113+
}
114+
}
115+
116+
# 2. 提取 HelpComment
117+
# 简单策略:查找第一个包含 .SYNOPSIS 或 .DESCRIPTION 的块注释
118+
foreach ($token in $tokens) {
119+
if ($token.Kind -eq 'Comment' -and $token.Text -match '^\s*<#\s*\.(SYNOPSIS|DESCRIPTION)') {
120+
$helpText = $token.Text
121+
break
122+
}
123+
}
124+
125+
# --- 生成 Shim 内容 ---
126+
$shimContentLines = @()
127+
$shimContentLines += "#!/usr/bin/env pwsh"
128+
$shimContentLines += ""
129+
$shimContentLines += "# Auto-generated shim by Manage-BinScripts.ps1"
130+
$shimContentLines += "# Source: $($script.FullName)"
131+
$shimContentLines += ""
132+
133+
if (-not [string]::IsNullOrWhiteSpace($helpText)) {
134+
$shimContentLines += $helpText
135+
$shimContentLines += ""
136+
}
137+
138+
if ($hasCmdletBinding) {
139+
$shimContentLines += $cmdletBindingText
140+
}
141+
elseif ($null -ne $paramBlockText) {
142+
# 如果有 param 但没有 CmdletBinding,为了支持高级功能(如 -Verbose),最好加上
143+
# 但为了保持原意,如果源脚本没加,我们也不加(除非为了 splatting 需要?)
144+
# 通常建议加上 [CmdletBinding()]
145+
$shimContentLines += "[CmdletBinding()]"
146+
}
147+
148+
if (-not [string]::IsNullOrWhiteSpace($paramBlockText)) {
149+
$shimContentLines += $paramBlockText
150+
$shimContentLines += ""
151+
}
152+
153+
$shimContentLines += "`$SourcePath = Join-Path `$PSScriptRoot '$sourceRelPath'"
154+
$shimContentLines += "if (-not (Test-Path `$SourcePath)) {"
155+
$shimContentLines += " Write-Error ""Cannot find source script at `$SourcePath"""
156+
$shimContentLines += " exit 1"
157+
$shimContentLines += "}"
158+
159+
# 调用逻辑
160+
if (-not [string]::IsNullOrWhiteSpace($paramBlockText)) {
161+
# 使用 @PSBoundParameters 透传绑定参数
162+
# 注意:如果 Shim 还有其他非绑定参数(如 $args),这里会丢失
163+
# 但既然有了 ParamBlock,通常只应该传递绑定的参数
164+
$shimContentLines += "& `$SourcePath @PSBoundParameters"
165+
}
166+
else {
167+
# 无 ParamBlock,透传所有 args
168+
$shimContentLines += "& `$SourcePath @args"
169+
}
170+
171+
$shimContentLines += "exit `$LASTEXITCODE"
106172

107173
# 写入 Shim 文件
108-
$shimContent | Set-Content -Path $targetPath -Encoding utf8NoBOM -Force
174+
$shimContentLines | Set-Content -Path $targetPath -Encoding utf8NoBOM -Force
109175

110176
# 在 Linux/macOS 上设置可执行权限
111177
if (-not $IsWindows) {

0 commit comments

Comments
 (0)