Skip to content

Commit d3da1e4

Browse files
committed
Re-implement CheckOperator to be consistent between PS versions & handle unary operators better
1 parent 3a47f4a commit d3da1e4

File tree

3 files changed

+452
-37
lines changed

3 files changed

+452
-37
lines changed

Engine/FindAstPositionVisitor.cs

+369
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Management.Automation.Language;
5+
6+
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer
7+
{
8+
/// <summary>
9+
/// Provides an efficient way to find the position in the AST corresponding to a given script position.
10+
/// </summary>
11+
#if !(PSV3 || PSV4)
12+
internal class FindAstPositionVisitor : AstVisitor2
13+
#else
14+
internal class FindAstPositionVisitor : AstVisitor
15+
#endif
16+
{
17+
private IScriptPosition searchPosition;
18+
19+
/// <summary>
20+
/// Contains the position in the AST corresponding to the provided <see cref="IScriptPosition"/> upon completion of the <see cref="Ast.Visit(AstVisitor)"/> method.
21+
/// </summary>
22+
public Ast AstPosition { get; private set; }
23+
24+
/// <summary>
25+
/// Initializes a new instance of the <see cref="FindAstPositionVisitor"/> class with the postition to search for.
26+
/// </summary>
27+
/// <param name="position">The script position to search for.</param>
28+
public FindAstPositionVisitor(IScriptPosition position)
29+
{
30+
this.searchPosition = position;
31+
}
32+
33+
/// <summary>
34+
/// Traverses the AST based on offests to find the leaf node which contains the provided <see cref="IScriptPosition"/>.
35+
/// This method implements the entire functionality of this visitor. All <see cref="AstVisitor2"/> methods are overridden to simply invoke this one.
36+
/// </summary>
37+
/// <param name="ast">Current AST node to process.</param>
38+
/// <returns>An <see cref="AstVisitAction"/> indicating whether to visit children of the current node.</returns>
39+
private AstVisitAction Visit(Ast ast)
40+
{
41+
if (ast.Extent.StartOffset > searchPosition.Offset || ast.Extent.EndOffset <= searchPosition.Offset)
42+
{
43+
return AstVisitAction.SkipChildren;
44+
}
45+
AstPosition = ast;
46+
return AstVisitAction.Continue;
47+
}
48+
49+
public override AstVisitAction VisitArrayExpression(ArrayExpressionAst arrayExpressionAst)
50+
{
51+
return Visit(arrayExpressionAst);
52+
}
53+
54+
public override AstVisitAction VisitArrayLiteral(ArrayLiteralAst arrayLiteralAst)
55+
{
56+
return Visit(arrayLiteralAst);
57+
}
58+
59+
public override AstVisitAction VisitAssignmentStatement(AssignmentStatementAst assignmentStatementAst)
60+
{
61+
return Visit(assignmentStatementAst);
62+
}
63+
64+
public override AstVisitAction VisitAttribute(AttributeAst attributeAst)
65+
{
66+
return Visit(attributeAst);
67+
}
68+
69+
public override AstVisitAction VisitAttributedExpression(AttributedExpressionAst attributedExpressionAst)
70+
{
71+
return Visit(attributedExpressionAst);
72+
}
73+
74+
public override AstVisitAction VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst)
75+
{
76+
return Visit(binaryExpressionAst);
77+
}
78+
79+
public override AstVisitAction VisitBlockStatement(BlockStatementAst blockStatementAst)
80+
{
81+
return Visit(blockStatementAst);
82+
}
83+
84+
public override AstVisitAction VisitBreakStatement(BreakStatementAst breakStatementAst)
85+
{
86+
return Visit(breakStatementAst);
87+
}
88+
89+
public override AstVisitAction VisitCatchClause(CatchClauseAst catchClauseAst)
90+
{
91+
return Visit(catchClauseAst);
92+
}
93+
94+
public override AstVisitAction VisitCommand(CommandAst commandAst)
95+
{
96+
return Visit(commandAst);
97+
}
98+
99+
public override AstVisitAction VisitCommandExpression(CommandExpressionAst commandExpressionAst)
100+
{
101+
return Visit(commandExpressionAst);
102+
}
103+
104+
public override AstVisitAction VisitCommandParameter(CommandParameterAst commandParameterAst)
105+
{
106+
return Visit(commandParameterAst);
107+
}
108+
109+
public override AstVisitAction VisitConstantExpression(ConstantExpressionAst constantExpressionAst)
110+
{
111+
return Visit(constantExpressionAst);
112+
}
113+
114+
public override AstVisitAction VisitContinueStatement(ContinueStatementAst continueStatementAst)
115+
{
116+
return Visit(continueStatementAst);
117+
}
118+
119+
public override AstVisitAction VisitConvertExpression(ConvertExpressionAst convertExpressionAst)
120+
{
121+
return Visit(convertExpressionAst);
122+
}
123+
124+
public override AstVisitAction VisitDataStatement(DataStatementAst dataStatementAst)
125+
{
126+
return Visit(dataStatementAst);
127+
}
128+
129+
public override AstVisitAction VisitDoUntilStatement(DoUntilStatementAst doUntilStatementAst)
130+
{
131+
return Visit(doUntilStatementAst);
132+
}
133+
134+
public override AstVisitAction VisitDoWhileStatement(DoWhileStatementAst doWhileStatementAst)
135+
{
136+
return Visit(doWhileStatementAst);
137+
}
138+
139+
public override AstVisitAction VisitErrorExpression(ErrorExpressionAst errorExpressionAst)
140+
{
141+
return Visit(errorExpressionAst);
142+
}
143+
144+
public override AstVisitAction VisitErrorStatement(ErrorStatementAst errorStatementAst)
145+
{
146+
return Visit(errorStatementAst);
147+
}
148+
149+
public override AstVisitAction VisitExitStatement(ExitStatementAst exitStatementAst)
150+
{
151+
return Visit(exitStatementAst);
152+
}
153+
154+
public override AstVisitAction VisitExpandableStringExpression(ExpandableStringExpressionAst expandableStringExpressionAst)
155+
{
156+
return Visit(expandableStringExpressionAst);
157+
}
158+
159+
public override AstVisitAction VisitFileRedirection(FileRedirectionAst fileRedirectionAst)
160+
{
161+
return Visit(fileRedirectionAst);
162+
}
163+
164+
public override AstVisitAction VisitForEachStatement(ForEachStatementAst forEachStatementAst)
165+
{
166+
return Visit(forEachStatementAst);
167+
}
168+
169+
public override AstVisitAction VisitForStatement(ForStatementAst forStatementAst)
170+
{
171+
return Visit(forStatementAst);
172+
}
173+
174+
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst)
175+
{
176+
return Visit(functionDefinitionAst);
177+
}
178+
179+
public override AstVisitAction VisitHashtable(HashtableAst hashtableAst)
180+
{
181+
return Visit(hashtableAst);
182+
}
183+
184+
public override AstVisitAction VisitIfStatement(IfStatementAst ifStatementAst)
185+
{
186+
return Visit(ifStatementAst);
187+
}
188+
189+
public override AstVisitAction VisitIndexExpression(IndexExpressionAst indexExpressionAst)
190+
{
191+
return Visit(indexExpressionAst);
192+
}
193+
194+
public override AstVisitAction VisitInvokeMemberExpression(InvokeMemberExpressionAst invokeMemberExpressionAst)
195+
{
196+
return Visit(invokeMemberExpressionAst);
197+
}
198+
199+
public override AstVisitAction VisitMemberExpression(MemberExpressionAst memberExpressionAst)
200+
{
201+
return Visit(memberExpressionAst);
202+
}
203+
204+
public override AstVisitAction VisitMergingRedirection(MergingRedirectionAst mergingRedirectionAst)
205+
{
206+
return Visit(mergingRedirectionAst);
207+
}
208+
209+
public override AstVisitAction VisitNamedAttributeArgument(NamedAttributeArgumentAst namedAttributeArgumentAst)
210+
{
211+
return Visit(namedAttributeArgumentAst);
212+
}
213+
214+
public override AstVisitAction VisitNamedBlock(NamedBlockAst namedBlockAst)
215+
{
216+
return Visit(namedBlockAst);
217+
}
218+
219+
public override AstVisitAction VisitParamBlock(ParamBlockAst paramBlockAst)
220+
{
221+
return Visit(paramBlockAst);
222+
}
223+
224+
public override AstVisitAction VisitParameter(ParameterAst parameterAst)
225+
{
226+
return Visit(parameterAst);
227+
}
228+
229+
public override AstVisitAction VisitParenExpression(ParenExpressionAst parenExpressionAst)
230+
{
231+
return Visit(parenExpressionAst);
232+
}
233+
234+
public override AstVisitAction VisitPipeline(PipelineAst pipelineAst)
235+
{
236+
return Visit(pipelineAst);
237+
}
238+
239+
public override AstVisitAction VisitReturnStatement(ReturnStatementAst returnStatementAst)
240+
{
241+
return Visit(returnStatementAst);
242+
}
243+
244+
public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst)
245+
{
246+
return Visit(scriptBlockAst);
247+
}
248+
249+
public override AstVisitAction VisitScriptBlockExpression(ScriptBlockExpressionAst scriptBlockExpressionAst)
250+
{
251+
return Visit(scriptBlockExpressionAst);
252+
}
253+
254+
public override AstVisitAction VisitStatementBlock(StatementBlockAst statementBlockAst)
255+
{
256+
return Visit(statementBlockAst);
257+
}
258+
259+
public override AstVisitAction VisitStringConstantExpression(StringConstantExpressionAst stringConstantExpressionAst)
260+
{
261+
return Visit(stringConstantExpressionAst);
262+
}
263+
264+
public override AstVisitAction VisitSubExpression(SubExpressionAst subExpressionAst)
265+
{
266+
return Visit(subExpressionAst);
267+
}
268+
269+
public override AstVisitAction VisitSwitchStatement(SwitchStatementAst switchStatementAst)
270+
{
271+
return Visit(switchStatementAst);
272+
}
273+
274+
public override AstVisitAction VisitThrowStatement(ThrowStatementAst throwStatementAst)
275+
{
276+
return Visit(throwStatementAst);
277+
}
278+
279+
public override AstVisitAction VisitTrap(TrapStatementAst trapStatementAst)
280+
{
281+
return Visit(trapStatementAst);
282+
}
283+
284+
public override AstVisitAction VisitTryStatement(TryStatementAst tryStatementAst)
285+
{
286+
return Visit(tryStatementAst);
287+
}
288+
289+
public override AstVisitAction VisitTypeConstraint(TypeConstraintAst typeConstraintAst)
290+
{
291+
return Visit(typeConstraintAst);
292+
}
293+
294+
public override AstVisitAction VisitTypeExpression(TypeExpressionAst typeExpressionAst)
295+
{
296+
return Visit(typeExpressionAst);
297+
}
298+
299+
public override AstVisitAction VisitUnaryExpression(UnaryExpressionAst unaryExpressionAst)
300+
{
301+
return Visit(unaryExpressionAst);
302+
}
303+
304+
public override AstVisitAction VisitUsingExpression(UsingExpressionAst usingExpressionAst)
305+
{
306+
return Visit(usingExpressionAst);
307+
}
308+
309+
public override AstVisitAction VisitVariableExpression(VariableExpressionAst variableExpressionAst)
310+
{
311+
return Visit(variableExpressionAst);
312+
}
313+
314+
public override AstVisitAction VisitWhileStatement(WhileStatementAst whileStatementAst)
315+
{
316+
return Visit(whileStatementAst);
317+
}
318+
319+
#if !(PSV3 || PSV4)
320+
public override AstVisitAction VisitBaseCtorInvokeMemberExpression(BaseCtorInvokeMemberExpressionAst baseCtorInvokeMemberExpressionAst)
321+
{
322+
return Visit(baseCtorInvokeMemberExpressionAst);
323+
}
324+
325+
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
326+
{
327+
return Visit(configurationDefinitionAst);
328+
}
329+
330+
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst)
331+
{
332+
return Visit(dynamicKeywordStatementAst);
333+
}
334+
335+
public override AstVisitAction VisitFunctionMember(FunctionMemberAst functionMemberAst)
336+
{
337+
return Visit(functionMemberAst);
338+
}
339+
340+
public override AstVisitAction VisitPropertyMember(PropertyMemberAst propertyMemberAst)
341+
{
342+
return Visit(propertyMemberAst);
343+
}
344+
345+
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst)
346+
{
347+
return Visit(typeDefinitionAst);
348+
}
349+
350+
public override AstVisitAction VisitUsingStatement(UsingStatementAst usingStatementAst)
351+
{
352+
return Visit(usingStatementAst);
353+
}
354+
#endif
355+
356+
#if !(NET452 || PSV6) // NET452 includes V3,4,5
357+
public override AstVisitAction VisitPipelineChain(PipelineChainAst pipelineChainAst)
358+
{
359+
return Visit(pipelineChainAst);
360+
}
361+
362+
public override AstVisitAction VisitTernaryExpression(TernaryExpressionAst ternaryExpressionAst)
363+
{
364+
return Visit(ternaryExpressionAst);
365+
}
366+
#endif
367+
368+
}
369+
}

Engine/TokenOperations.cs

+13
Original file line numberDiff line numberDiff line change
@@ -232,5 +232,18 @@ private bool OnSameLine(Token token1, Token token2)
232232
{
233233
return token1.Extent.StartLineNumber == token2.Extent.EndLineNumber;
234234
}
235+
236+
/// <summary>
237+
/// Finds the position of a given token in the AST.
238+
/// </summary>
239+
/// <param name="token">The <see cref="Token"/> to search for.</param>
240+
/// <returns>The Ast node directly containing the provided <see cref="Token"/>.</returns>
241+
public Ast GetAstPosition(Token token)
242+
{
243+
FindAstPositionVisitor findAstVisitor = new FindAstPositionVisitor(token.Extent.StartScriptPosition);
244+
ast.Visit(findAstVisitor);
245+
return findAstVisitor.AstPosition;
246+
}
247+
235248
}
236249
}

0 commit comments

Comments
 (0)