@@ -31,31 +31,6 @@ public VariableAnalysis(IFlowGraph decorated) : base(decorated) { }
31
31
private readonly List < LoopGotoTargets > _loopTargets = new List < LoopGotoTargets > ( ) ;
32
32
private Dictionary < string , VariableAnalysisDetails > VariablesDictionary ;
33
33
34
- /// <summary>
35
- /// Used to analyze scriptbloct, functionmemberast or functiondefinitionast
36
- /// </summary>
37
- /// <param name="ast"></param>
38
- /// <returns></returns>
39
- public static void Analyze ( Ast ast )
40
- {
41
- if ( ast == null ) return ;
42
-
43
- ( new VariableAnalysis ( new FlowGraph ( ) ) ) . AnalyzeImpl ( ast ) ;
44
- }
45
-
46
- /// <summary>
47
- /// Analyze a member function, marking variable references as "dynamic" (so they can be reported as errors)
48
- /// and also analyze the control flow to make sure every block returns (or throws)
49
- /// </summary>
50
- /// <param name="ast"></param>
51
- /// <returns></returns>
52
- public static bool AnalyzeMemberFunction ( Ast ast )
53
- {
54
- VariableAnalysis va = ( new VariableAnalysis ( new FlowGraph ( ) ) ) ;
55
- va . AnalyzeImpl ( ast ) ;
56
- return va . Exit . _predecessors . All ( b => b . _returns || b . _throws || b . _unreachable ) ;
57
- }
58
-
59
34
/// <summary>
60
35
/// Return parameters of a functionmemberast or functiondefinitionast
61
36
/// </summary>
@@ -86,10 +61,8 @@ private IEnumerable<ParameterAst> FindParameters(Ast ast, Type type)
86
61
}
87
62
}
88
63
89
- private Dictionary < String , VariableTarget > ProcessParameters ( IEnumerable < ParameterAst > parameters )
64
+ private void ProcessParameters ( IEnumerable < ParameterAst > parameters )
90
65
{
91
- Dictionary < String , VariableTarget > varTargets = new Dictionary < String , VariableTarget > ( ) ;
92
-
93
66
foreach ( var parameter in parameters )
94
67
{
95
68
var variablePath = parameter . Name . VariablePath ;
@@ -128,7 +101,7 @@ private Dictionary<String, VariableTarget> ProcessParameters(IEnumerable<Paramet
128
101
129
102
var varName = AssignmentTarget . GetUnaliasedVariableName ( variablePath ) ;
130
103
var details = _variables [ varName ] ;
131
- type = type ?? details . Type ?? typeof ( object ) ;
104
+ details . Type = type ?? details . Type ?? typeof ( object ) ;
132
105
133
106
if ( parameter . DefaultValue != null )
134
107
{
@@ -147,24 +120,13 @@ private Dictionary<String, VariableTarget> ProcessParameters(IEnumerable<Paramet
147
120
// Consider switch or mandatory parameter as already initialized
148
121
Entry . AddAst ( new AssignmentTarget ( varName , type ) ) ;
149
122
}
150
- else if ( type != typeof ( object ) )
123
+ else
151
124
{
152
125
VariableTarget varTarget = new VariableTarget ( parameter . Name ) ;
153
- varTarget . Type = type ;
154
- if ( ! varTargets . ContainsKey ( varTarget . Name ) )
155
- {
156
- varTargets . Add ( varTarget . Name , varTarget ) ;
157
- }
158
-
126
+ varTarget . Type = details . Type ;
159
127
Entry . AddAst ( varTarget ) ;
160
128
}
161
- else
162
- {
163
- Entry . AddAst ( new VariableTarget ( parameter . Name ) ) ;
164
- }
165
129
}
166
-
167
- return varTargets ;
168
130
}
169
131
170
132
/// <summary>
@@ -181,24 +143,22 @@ public void AnalyzeImpl(Ast ast)
181
143
182
144
_variables = FindAllVariablesVisitor . Visit ( ast ) ;
183
145
184
- Dictionary < String , VariableTarget > varTargets = null ;
185
-
186
146
Init ( ) ;
187
147
188
148
if ( ast is FunctionMemberAst || ast is FunctionDefinitionAst )
189
149
{
190
150
IEnumerable < ParameterAst > parameters = FindParameters ( ast , ast . GetType ( ) ) ;
191
151
if ( parameters != null )
192
152
{
193
- varTargets = ProcessParameters ( parameters ) ;
153
+ ProcessParameters ( parameters ) ;
194
154
}
195
155
}
196
156
else
197
157
{
198
158
ScriptBlockAst sbAst = ast as ScriptBlockAst ;
199
159
if ( sbAst != null && sbAst . ParamBlock != null && sbAst . ParamBlock . Parameters != null )
200
160
{
201
- varTargets = ProcessParameters ( sbAst . ParamBlock . Parameters ) ;
161
+ ProcessParameters ( sbAst . ParamBlock . Parameters ) ;
202
162
}
203
163
}
204
164
@@ -215,29 +175,18 @@ public void AnalyzeImpl(Ast ast)
215
175
ast . Visit ( this . Decorator ) ;
216
176
}
217
177
218
- VariablesDictionary = Block . SparseSimpleConstants ( _variables , Entry ) ;
178
+ Ast parent = ast ;
219
179
220
- // Update the type of variables in VariablesDictionary based on the param block
221
- foreach ( var entry in VariablesDictionary )
180
+ while ( parent . Parent != null )
222
181
{
223
- var analysisDetails = entry . Value ;
224
- if ( analysisDetails . Type != typeof ( Unreached ) )
225
- {
226
- continue ;
227
- }
228
-
229
- // This regex is used to extracts the variable name from entry.Key. The key is of the form [varname]s[so]e[eo]
230
- // where [varname] is name of variable [so] is the start offset number and [eo] is the end offset number
231
- var result = Regex . Match ( entry . Key , "^(.+)s[0-9]+e[0-9]+$" ) ;
232
- if ( result . Success && result . Groups . Count == 2 )
233
- {
234
- string varName = result . Groups [ 1 ] . Value ;
235
- if ( varTargets . ContainsKey ( varName ) )
236
- {
237
- analysisDetails . Type = varTargets [ varName ] . Type ;
238
- }
239
- }
182
+ parent = parent . Parent ;
240
183
}
184
+
185
+ List < TypeDefinitionAst > classes = parent . FindAll ( item =>
186
+ item is TypeDefinitionAst && ( item as TypeDefinitionAst ) . IsClass , true )
187
+ . Cast < TypeDefinitionAst > ( ) . ToList ( ) ;
188
+
189
+ VariablesDictionary = Block . SparseSimpleConstants ( _variables , Entry , classes ) ;
241
190
}
242
191
243
192
/// <summary>
@@ -292,7 +241,7 @@ public bool IsUninitialized(VariableExpressionAst varTarget)
292
241
}
293
242
294
243
var analysis = GetVariableAnalysis ( varTarget ) ;
295
-
244
+
296
245
if ( analysis == null )
297
246
{
298
247
return false ;
@@ -315,9 +264,9 @@ public bool IsGlobalOrEnvironment(VariableExpressionAst varTarget)
315
264
return ( varTarget . VariablePath . IsGlobal
316
265
|| String . Equals ( varTarget . VariablePath . DriveName , "env" , StringComparison . OrdinalIgnoreCase ) ) ;
317
266
}
318
-
267
+
319
268
return false ;
320
-
269
+
321
270
}
322
271
323
272
/// <summary>
@@ -391,7 +340,7 @@ public override object VisitAssignmentStatement(AssignmentStatementAst assignmen
391
340
// We skip things like $a.test = 3. In this case we will just test
392
341
// for variable $a
393
342
assignTarget . Visit ( this . Decorator ) ;
394
- }
343
+ }
395
344
}
396
345
397
346
return null ;
0 commit comments