Skip to content

Commit ae450c8

Browse files
author
James Brundage
committed
Adding VariableExpressionAst.GetVariableType() (#156)
1 parent e0f0b50 commit ae450c8

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<#
2+
.SYNOPSIS
3+
Gets a Variable's Likely Type
4+
.DESCRIPTION
5+
Determines the type of a variable.
6+
7+
This looks for the closest assignment statement and uses this to determine what type the variable is likely to be.
8+
.NOTES
9+
Subject to revision and improvement. While this covers many potential scenarios, it does not always
10+
.EXAMPLE
11+
{
12+
[int]$x = 1
13+
$y = 2
14+
$x + $y
15+
}.Ast.EndBlock.Statements[-1].PipelineElements[0].Expression.Left.GetVariableType()
16+
.EXAMPLE
17+
{
18+
$x = Get-Process
19+
$x + $y
20+
}.Ast.EndBlock.Statements[-1].PipelineElements[0].Expression.Left.GetVariableType()
21+
#>
22+
if ($this.VariablePath.userPath -eq 'psBoundParmeters') {
23+
return [Management.Automation.PSBoundParametersDictionary]
24+
}
25+
$assignments = $this.GetAssignments()
26+
$closestAssignment = $assignments[0]
27+
28+
# Our easiest scenario is that the variable is assigned in a parameter
29+
if ($closestAssignment -is [Management.Automation.Language.ParameterAst]) {
30+
# If so, the .StaticType will give us our variable type.
31+
return $closestAssignment.StaticType
32+
}
33+
34+
# Our next simple scenario is that the closest assignment is declaring a hashtable
35+
if ($closestAssignment.Right.Expression -is [Management.Automation.Language.HashtableAst]) {
36+
return [hashtable]
37+
}
38+
39+
# The left can be a convert expression.
40+
if ($closestAssignment.Left -is [Management.Automation.Language.ConvertExpressionAst]) {
41+
# If the left was [ordered]
42+
if ($closestAssignment.Left.Type.Tostring() -eq '[ordered]') {
43+
return [Collections.specialized.OrderedDictionary] # return an OrderedDictionary
44+
} else {
45+
# If the left side's type can be reflected
46+
$reflectedType = $closestAssignment.Left.Type.TypeName.GetReflectionType()
47+
if ($reflectedType) {
48+
return $reflectedType # return it.
49+
}
50+
else {
51+
# otherwise, return the left's static type.
52+
return $closestAssignment.Left.StaticType
53+
}
54+
}
55+
}
56+
57+
# Determine if the left side is multiple assignment
58+
$isMultiAssignment =$closestAssignment.Left -is [Management.Automation.Language.ArrayLiteralAst]
59+
60+
# If the left side is not multiple assignment, but the right side is an array
61+
if (-not $isMultiAssignment -and
62+
$closestAssignment.Right.Expression -is [Management.Automation.ArrayExpressionAst]) {
63+
# then the object is an array.
64+
return [Object[]]
65+
}
66+
67+
# Next, if the right as a convert expression
68+
if ($closestAssignment.Right.Expression -is [Management.Automation.Language.ConvertExpressionAst]) {
69+
# If it was '[ordered]'
70+
if ($closestAssignment.Right.Expression.Type.Tostring() -eq '[ordered]') {
71+
# return an ordered dictionary
72+
return [Collections.specialized.OrderedDictionary]
73+
} else {
74+
# Otherwise, see if we have a reflected type.
75+
$reflectedType = $closestAssignment.Right.Expression.Type.TypeName.GetReflectionType()
76+
if ($reflectedType) {
77+
return $reflectedType # If we do, return it.
78+
}
79+
else {
80+
# If we don't, return the static type of the expression
81+
return $closestAssignment.Right.Expression.StaticType
82+
}
83+
}
84+
}
85+
86+
87+
88+
89+
# The right side could be a pipeline
90+
if ($closestAssignment.Right -is [Management.Automation.Language.PipelineAst]) {
91+
# If so, walk backwards thru the pipeline
92+
for ($pipelineElementIndex = $closestAssignment.Right.PipelineElements.Count - 1;
93+
$pipelineElementIndex -ge 0;
94+
$pipelineElementIndex--) {
95+
$commandInfo = $closestAssignment.Right.PipelineElements[$pipelineElementIndex].ResolvedCommand
96+
# If the command had an output type, return it.
97+
if ($commandInfo.OutputType) {
98+
return $commandInfo.OutputType.Type
99+
}
100+
}
101+
}
102+
103+
104+
105+
106+
107+
108+
# If we don't know, return nothing
109+
return
110+
111+
112+
113+

0 commit comments

Comments
 (0)