@@ -199,6 +199,12 @@ $this.Parent.PipelineElements.IndexOf($this)
199199
200200 </GetScriptBlock >
201201 </ScriptProperty >
202+ <ScriptProperty >
203+ <Name >ResolvedCommand</Name >
204+ <GetScriptBlock >
205+ $ExecutionContext.SessionState.InvokeCommand.GetCommand($this.CommandElements[0].ToString(), 'All')
206+ </GetScriptBlock >
207+ </ScriptProperty >
202208 </Members >
203209 </Type >
204210 <Type >
@@ -300,6 +306,179 @@ if ($this.variablePath.userPath -in 'true', 'false', 'null') {
300306 $this
301307}
302308
309+ </Script >
310+ </ScriptMethod >
311+ <ScriptMethod >
312+ <Name >GetAssignments</Name >
313+ <Script >
314+ < #
315+ .SYNOPSIS
316+ Gets assignments of a variable
317+ .DESCRIPTION
318+ Searches the abstract syntax tree for assignments of the variable.
319+ .EXAMPLE
320+ {
321+ $x = 1
322+ $y = 2
323+ $x * $y
324+ }.Ast.EndBlock.Statements[-1].PipelineElements[0].Expression.Left.GetAssignments()
325+ .EXAMPLE
326+ {
327+ [int]$x, [int]$y = 1, 2
328+ $x * $y
329+ }.Ast.EndBlock.Statements[-1].PipelineElements[0].Expression.Left.GetAssignments()
330+ .EXAMPLE
331+ {
332+ param($x, $y)
333+ $x * $y
334+ }.Ast.EndBlock.Statements[-1].PipelineElements[0].Expression.Left.GetAssignments()
335+ #>
336+ param()
337+
338+ $astVariableName = "$this"
339+ $variableFoundAt = @{}
340+ foreach ($parent in $this.GetLineage()) {
341+ $parent.FindAll({
342+ param($ast)
343+ $IsAssignment =
344+ (
345+ $ast -is [Management.Automation.Language.AssignmentStatementAst] -and
346+ $ast.Left.Find({
347+ param($leftAst)
348+ $leftAst -is [Management.Automation.Language.VariableExpressionAST] -and
349+ $leftAst.Extent.ToString() -eq $astVariableName
350+ }, $false)
351+ ) -or (
352+ $ast -is [Management.Automation.Language.ParameterAst] -and
353+ $ast.Name.ToString() -eq $astVariableName
354+ )
355+
356+ if ($IsAssignment -and -not $variableFoundAt[$ast.Extent.StartOffset]) {
357+ $variableFoundAt[$ast.Extent.StartOffset] = $ast
358+ $ast
359+ }
360+ }, $false)
361+ }
362+
363+ </Script >
364+ </ScriptMethod >
365+ <ScriptMethod >
366+ <Name >GetVariableType</Name >
367+ <Script >
368+ < #
369+ .SYNOPSIS
370+ Gets a Variable's Likely Type
371+ .DESCRIPTION
372+ Determines the type of a variable.
373+
374+ This looks for the closest assignment statement and uses this to determine what type the variable is likely to be.
375+ .NOTES
376+ Subject to revision and improvement. While this covers many potential scenarios, it does not always
377+ .EXAMPLE
378+ {
379+ [int]$x = 1
380+ $y = 2
381+ $x + $y
382+ }.Ast.EndBlock.Statements[-1].PipelineElements[0].Expression.Left.GetVariableType()
383+ .EXAMPLE
384+ {
385+ $x = Get-Process
386+ $x + $y
387+ }.Ast.EndBlock.Statements[-1].PipelineElements[0].Expression.Left.GetVariableType()
388+ #>
389+ if ($this.VariablePath.userPath -eq 'psBoundParmeters') {
390+ return [Management.Automation.PSBoundParametersDictionary]
391+ }
392+ $assignments = $this.GetAssignments()
393+ $closestAssignment = $assignments[0]
394+
395+ # Our easiest scenario is that the variable is assigned in a parameter
396+ if ($closestAssignment -is [Management.Automation.Language.ParameterAst]) {
397+ # If so, the .StaticType will give us our variable type.
398+ return $closestAssignment.StaticType
399+ }
400+
401+ # Our next simple scenario is that the closest assignment is declaring a hashtable
402+ if ($closestAssignment.Right.Expression -is [Management.Automation.Language.HashtableAst]) {
403+ return [hashtable]
404+ }
405+
406+ # The left can be a convert expression.
407+ if ($closestAssignment.Left -is [Management.Automation.Language.ConvertExpressionAst]) {
408+ # If the left was [ordered]
409+ if ($closestAssignment.Left.Type.Tostring() -eq '[ordered]') {
410+ return [Collections.specialized.OrderedDictionary] # return an OrderedDictionary
411+ } else {
412+ # If the left side's type can be reflected
413+ $reflectedType = $closestAssignment.Left.Type.TypeName.GetReflectionType()
414+ if ($reflectedType) {
415+ return $reflectedType # return it.
416+ }
417+ else {
418+ # otherwise, return the left's static type.
419+ return $closestAssignment.Left.StaticType
420+ }
421+ }
422+ }
423+
424+ # Determine if the left side is multiple assignment
425+ $isMultiAssignment =$closestAssignment.Left -is [Management.Automation.Language.ArrayLiteralAst]
426+
427+ # If the left side is not multiple assignment, but the right side is an array
428+ if (-not $isMultiAssignment -and
429+ $closestAssignment.Right.Expression -is [Management.Automation.ArrayExpressionAst]) {
430+ # then the object is an array.
431+ return [Object[]]
432+ }
433+
434+ # Next, if the right as a convert expression
435+ if ($closestAssignment.Right.Expression -is [Management.Automation.Language.ConvertExpressionAst]) {
436+ # If it was '[ordered]'
437+ if ($closestAssignment.Right.Expression.Type.Tostring() -eq '[ordered]') {
438+ # return an ordered dictionary
439+ return [Collections.specialized.OrderedDictionary]
440+ } else {
441+ # Otherwise, see if we have a reflected type.
442+ $reflectedType = $closestAssignment.Right.Expression.Type.TypeName.GetReflectionType()
443+ if ($reflectedType) {
444+ return $reflectedType # If we do, return it.
445+ }
446+ else {
447+ # If we don't, return the static type of the expression
448+ return $closestAssignment.Right.Expression.StaticType
449+ }
450+ }
451+ }
452+
453+
454+
455+
456+ # The right side could be a pipeline
457+ if ($closestAssignment.Right -is [Management.Automation.Language.PipelineAst]) {
458+ # If so, walk backwards thru the pipeline
459+ for ($pipelineElementIndex = $closestAssignment.Right.PipelineElements.Count - 1;
460+ $pipelineElementIndex -ge 0;
461+ $pipelineElementIndex--) {
462+ $commandInfo = $closestAssignment.Right.PipelineElements[$pipelineElementIndex].ResolvedCommand
463+ # If the command had an output type, return it.
464+ if ($commandInfo.OutputType) {
465+ return $commandInfo.OutputType.Type
466+ }
467+ }
468+ }
469+
470+
471+
472+
473+
474+
475+ # If we don't know, return nothing
476+ return
477+
478+
479+
480+
481+
303482 </Script >
304483 </ScriptMethod >
305484 </Members >
0 commit comments