Add -DefaultValueType to Should -HaveParameter#2898
Draft
nohwnd wants to merge 4 commits into
Draft
Conversation
Surface the parameter default value's expression kind (the AST node type of the default value) so assertions can distinguish an expression default like $Path = (Get-DefaultPath) from a string-literal default like $Path = '(Get-DefaultPath)', which share the same -DefaultValue string. The new -DefaultValueType parameter is added to both the legacy Should -HaveParameter operator and the assert-style Should-HaveParameter, and is matched case-insensitively with an optional trailing 'Ast'. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
nohwnd
marked this pull request as draft
July 17, 2026 21:01
Member
Author
|
doubt that people want to write StringConstantExpressionAst as the expected type of the parameter. need to iterate |
The first version required the raw AST node type, like ParenExpressionAst or StringConstantExpressionAst, which you cannot know without reading the PowerShell parser internals. Use a ValidateSet of friendly kinds instead: String, InterpolatedString, Number, Variable, Expression, ScriptBlock, Array, Hashtable, and map each to the AST type(s) internally. This gives tab completion on Should-HaveParameter and a clear error that lists the valid kinds when you pass something wrong, instead of a confusing assertion failure. Failure messages show the friendly kind on both sides now. $true, $false and $null are Variable, and the help says so. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
$true is Boolean now, not Variable. A default has a real type when the parser can type it statically, so report that: Boolean, Null, Number, String, ScriptBlock, Array, Hashtable. A computed default like (Get-Date) or [datetime]::Now has no static type, PowerShell reports it as System.Object, so it stays Expression, which is also what tells it apart from a literal string default. Interpolated strings are String, a bare $var is Expression. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The two things #1888 wants to tell apart, (Get-DefaultPath) and '(Get-DefaultPath)', are the same type, so a type alone cannot separate them. The real difference is that one is a computed expression and one is a literal. So -DefaultValueType now takes a real .NET type, as a [type] or a type name the same way -Type does, matched against the type of a literal default ($Force = $false is [bool], $Retries = 3 is [int]). For a computed default like (Get-Date) whose type is not known until it runs, pass the special value Expression. Expression vs a concrete type is what distinguishes the two cases from the issue. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix #1888
Adds
-DefaultValueTypeto bothShould -HaveParameterand the assert-styleShould-HaveParameter.The issue wants to tell an expression default apart from a string literal that has the same
-DefaultValuetext. The catch is that the two are the same type:(Get-DefaultPath)returns a path string and'(Get-DefaultPath)'is a string, so a type alone cannot separate them. The real difference is that one is a computed expression and the other is a literal.So
-DefaultValueTypetakes a real .NET type, given as a[type]or a type name the same way-Typeis given, matched against the type of a literal default. For a computed default whose type is not known until it runs, you pass the special valueExpression:Notes:
[type](([bool])) or a type name string (bool,int,string,datetime), same as-Type. An unknown type name throws, and points you at-DefaultValueType Expression.Expressioncovers any computed default whose type is not statically known, e.g.(Get-Date),[datetime]::Now,$someVariable. You cannot assert a concrete type for those, because the type is only known once the code runs.$true/$falseare[bool], a number is[int]/[double],{ ... }is[scriptblock],@{ }is[hashtable]. A$nulldefault has no type. An interpolated string like"$x bar"is[string].the default value to be of type [System.Int32], but the default value was of type [System.String], orthe default value to be an expression, but the default value was of type [System.String].HaveParameter.ps1andShould-HaveParameter.ps1plus tests for both. All existing-HaveParameterbehavior is unchanged.test.ps1for the affected files: 202 passed, no new analyzer findings.