MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5 6namespace System.Management.Automation7{8 /// <summary>9 /// Enumerates the items matching a particular name in the scopes specified using10 /// the appropriate scoping lookup rules.11 /// </summary>12 /// <typeparam name="T">13 /// The type of items that the derived class returns.14 /// </typeparam>15 internal abstract class ScopedItemSearcher<T> : IEnumerator<T>, IEnumerable<T>16 {17 #region ctor18 19 /// <summary>20 /// Constructs a scoped item searcher.21 /// </summary>22 /// <param name="sessionState">23 /// The state of the engine instance to enumerate through the scopes.24 /// </param>25 /// <param name="lookupPath">26 /// The parsed name of the item to lookup.27 /// </param>28 /// <exception cref="ArgumentNullException">29 /// If <paramref name="sessionState"/> or <paramref name="lookupPath"/>30 /// is null.31 /// </exception>32 internal ScopedItemSearcher(33 SessionStateInternal sessionState,34 VariablePath lookupPath)35 {36 if (sessionState == null)37 {38 throw PSTraceSource.NewArgumentNullException(nameof(sessionState));39 }40 41 if (lookupPath == null)42 {43 throw PSTraceSource.NewArgumentNullException(nameof(lookupPath));44 }45 46 this.sessionState = sessionState;47 _lookupPath = lookupPath;48 InitializeScopeEnumerator();49 }50 51 #endregion ctor52 53 #region IEnumerable/IEnumerator members54 55 /// <summary>56 /// Gets the current object as an IEnumerator.57 /// </summary>58 /// <returns>59 /// The current object as an IEnumerator.60 /// </returns>61 System.Collections.Generic.IEnumerator<T> System.Collections.Generic.IEnumerable<T>.GetEnumerator()62 {63 return this;64 }65 66 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()67 {68 return this;69 }70 71 /// <summary>72 /// Moves the enumerator to the next matching scoped item.73 /// </summary>74 /// <returns>75 /// True if another matching scoped item was found, or false otherwise.76 /// </returns>77 public bool MoveNext()78 {79 bool result = true;80 81 if (!_isInitialized)82 {83 InitializeScopeEnumerator();84 }85 86 // Enumerate the scopes until a matching scoped item is found87 88 while (_scopeEnumerable.MoveNext())89 {90 T newCurrentItem;91 92 if (TryGetNewScopeItem(((IEnumerator<SessionStateScope>)_scopeEnumerable).Current, out newCurrentItem))93 {94 _currentScope = ((IEnumerator<SessionStateScope>)_scopeEnumerable).Current;95 _current = newCurrentItem;96 result = true;97 break;98 }99 100 result = false;101 102 if (_isSingleScopeLookup)103 {104 break;105 }106 }107 108 return result;109 }110 111 /// <summary>112 /// Gets the current scoped item.113 /// </summary>114 T IEnumerator<T>.Current115 {116 get117 {118 return _current;119 }120 }121 122 public object Current123 {124 get125 {126 return _current;127 }128 }129 130 public void Reset()131 {132 InitializeScopeEnumerator();133 }134 135 public void Dispose()136 {137 _current = default(T);138 _scopeEnumerable.Dispose();139 _scopeEnumerable = null;140 _isInitialized = false;141 GC.SuppressFinalize(this);142 }143 144 /// <summary>145 /// Derived classes override this method to return their146 /// particular type of scoped item.147 /// </summary>148 /// <param name="scope">149 /// The scope to look the item up in.150 /// </param>151 /// <param name="name">152 /// The name of the item to retrieve.153 /// </param>154 /// <param name="newCurrentItem">155 /// The scope item that the derived class should return.156 /// </param>157 /// <returns>158 /// True if the scope item was found or false otherwise.159 /// </returns>160 protected abstract bool GetScopeItem(161 SessionStateScope scope,162 VariablePath name,163 out T newCurrentItem);164 165 #endregion IEnumerable/IEnumerator members166 167 /// <summary>168 /// Gets the lookup scope that the Current item was found in.169 /// </summary>170 internal SessionStateScope CurrentLookupScope171 {172 get { return _currentScope; }173 }174 175 private SessionStateScope _currentScope;176 177 /// <summary>178 /// Gets the scope in which the search begins.179 /// </summary>180 internal SessionStateScope InitialScope181 {182 get { return _initialScope; }183 }184 185 private SessionStateScope _initialScope;186 187 #region private members188 189 private bool TryGetNewScopeItem(190 SessionStateScope lookupScope,191 out T newCurrentItem)192 {193 bool result = GetScopeItem(194 lookupScope,195 _lookupPath,196 out newCurrentItem);197 198 return result;199 }200 201 private void InitializeScopeEnumerator()202 {203 // Define the lookup scope and if we have to do single204 // level or dynamic lookup based on the lookup variable205 206 _initialScope = sessionState.CurrentScope;207 208 if (_lookupPath.IsGlobal)209 {210 _initialScope = sessionState.GlobalScope;211 _isSingleScopeLookup = true;212 }213 else if (_lookupPath.IsLocal ||214 _lookupPath.IsPrivate)215 {216 _initialScope = sessionState.CurrentScope;217 _isSingleScopeLookup = true;218 }219 else if (_lookupPath.IsScript)220 {221 _initialScope = sessionState.ScriptScope;222 _isSingleScopeLookup = true;223 }224 225 _scopeEnumerable =226 new SessionStateScopeEnumerator(_initialScope);227 228 _isInitialized = true;229 }230 231 private T _current;232 protected SessionStateInternal sessionState;233 private readonly VariablePath _lookupPath;234 private SessionStateScopeEnumerator _scopeEnumerable;235 private bool _isSingleScopeLookup;236 private bool _isInitialized;237 238 #endregion private members239 }240 241 /// <summary>242 /// The scope searcher for variables.243 /// </summary>244 internal class VariableScopeItemSearcher : ScopedItemSearcher<PSVariable>245 {246 public VariableScopeItemSearcher(247 SessionStateInternal sessionState,248 VariablePath lookupPath,249 CommandOrigin origin) : base(sessionState, lookupPath)250 {251 _origin = origin;252 }253 254 private readonly CommandOrigin _origin;255 256 /// <summary>257 /// Derived classes override this method to return their258 /// particular type of scoped item.259 /// </summary>260 /// <param name="scope">261 /// The scope to look the item up in.262 /// </param>263 /// <param name="name">264 /// The name of the item to retrieve.265 /// </param>266 /// <param name="variable">267 /// The scope item that the derived class should return.268 /// </param>269 /// <returns>270 /// True if the scope item was found or false otherwise.271 /// </returns>272 protected override bool GetScopeItem(273 SessionStateScope scope,274 VariablePath name,275 out PSVariable variable)276 {277 Diagnostics.Assert(name is not FunctionLookupPath,278 "name was scanned incorrect if we get here and it is a FunctionLookupPath");279 280 bool result = true;281 282 variable = scope.GetVariable(name.QualifiedName, _origin);283 284 // If the variable is private and the lookup scope285 // isn't the current scope, claim that the variable286 // doesn't exist so that the lookup continues.287 288 if (variable == null ||289 (variable.IsPrivate &&290 scope != sessionState.CurrentScope))291 {292 result = false;293 }294 295 return result;296 }297 }298 299 /// <summary>300 /// The scope searcher for aliases.301 /// </summary>302 internal class AliasScopeItemSearcher : ScopedItemSearcher<AliasInfo>303 {304 public AliasScopeItemSearcher(305 SessionStateInternal sessionState,306 VariablePath lookupPath) : base(sessionState, lookupPath)307 {308 }309 310 /// <summary>311 /// Derived classes override this method to return their312 /// particular type of scoped item.313 /// </summary>314 /// <param name="scope">315 /// The scope to look the item up in.316 /// </param>317 /// <param name="name">318 /// The name of the item to retrieve.319 /// </param>320 /// <param name="alias">321 /// The scope item that the derived class should return.322 /// </param>323 /// <returns>324 /// True if the scope item was found or false otherwise.325 /// </returns>326 protected override bool GetScopeItem(327 SessionStateScope scope,328 VariablePath name,329 out AliasInfo alias)330 {331 Diagnostics.Assert(name is not FunctionLookupPath,332 "name was scanned incorrect if we get here and it is a FunctionLookupPath");333 334 bool result = true;335 alias = scope.GetAlias(name.QualifiedName);336 337 // If the alias is private and the lookup scope338 // isn't the current scope, claim that the alias339 // doesn't exist so that the lookup continues.340 341 if (alias == null ||342 ((alias.Options & ScopedItemOptions.Private) != 0 &&343 scope != sessionState.CurrentScope))344 {345 result = false;346 }347 348 return result;349 }350 }351 352 /// <summary>353 /// The scope searcher for functions.354 /// </summary>355 internal class FunctionScopeItemSearcher : ScopedItemSearcher<FunctionInfo>356 {357 public FunctionScopeItemSearcher(358 SessionStateInternal sessionState,359 VariablePath lookupPath,360 CommandOrigin origin) : base(sessionState, lookupPath)361 {362 _origin = origin;363 }364 365 private readonly CommandOrigin _origin;366 367 /// <summary>368 /// Derived classes override this method to return their369 /// particular type of scoped item.370 /// </summary>371 /// <param name="scope">372 /// The scope to look the item up in.373 /// </param>374 /// <param name="path">375 /// The name of the item to retrieve.376 /// </param>377 /// <param name="script">378 /// The scope item that the derived class should return.379 /// </param>380 /// <returns>381 /// True if the scope item was found or false otherwise.382 /// </returns>383 protected override bool GetScopeItem(384 SessionStateScope scope,385 VariablePath path,386 out FunctionInfo script)387 {388 Diagnostics.Assert(path is FunctionLookupPath,389 "name was scanned incorrect if we get here and it is not a FunctionLookupPath");390 391 bool result = true;392 393 _name = path.IsFunction ? path.UnqualifiedPath : path.QualifiedName;394 395 script = scope.GetFunction(_name);396 397 if (script != null)398 {399 bool isPrivate;400 FilterInfo filterInfo = script as FilterInfo;401 if (filterInfo != null)402 {403 isPrivate = (filterInfo.Options & ScopedItemOptions.Private) != 0;404 }405 else406 {407 isPrivate = (script.Options & ScopedItemOptions.Private) != 0;408 }409 410 // If the function is private and the lookup scope411 // isn't the current scope, claim that the function412 // doesn't exist so that the lookup continues.413 414 if (isPrivate &&415 scope != sessionState.CurrentScope)416 {417 result = false;418 }419 else420 {421 // Now check the visibility of the variable...422 SessionState.ThrowIfNotVisible(_origin, script);423 }424 }425 else426 {427 result = false;428 }429 430 return result;431 }432 433 internal string Name434 {435 get { return _name; }436 }437 438 private string _name = string.Empty;439 }440 441 /// <summary>442 /// The scope searcher for drives.443 /// </summary>444 internal class DriveScopeItemSearcher : ScopedItemSearcher<PSDriveInfo>445 {446 public DriveScopeItemSearcher(447 SessionStateInternal sessionState,448 VariablePath lookupPath) : base(sessionState, lookupPath)449 {450 }451 452 /// <summary>453 /// Derived classes override this method to return their454 /// particular type of scoped item.455 /// </summary>456 /// <param name="scope">457 /// The scope to look the item up in.458 /// </param>459 /// <param name="name">460 /// The name of the item to retrieve.461 /// </param>462 /// <param name="drive">463 /// The scope item that the derived class should return.464 /// </param>465 /// <returns>466 /// True if the scope item was found or false otherwise.467 /// </returns>468 protected override bool GetScopeItem(469 SessionStateScope scope,470 VariablePath name,471 out PSDriveInfo drive)472 {473 Diagnostics.Assert(name is not FunctionLookupPath,474 "name was scanned incorrect if we get here and it is a FunctionLookupPath");475 476 bool result = true;477 drive = scope.GetDrive(name.DriveName);478 479 if (drive == null)480 {481 result = false;482 }483 484 return result;485 }486 }487}488 