MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6 7namespace System.Management.Automation8{9 /// <summary>10 /// HelpErrorTracer is a class to help tracing errors happened during loading11 /// help content for a help topic.12 ///13 /// This class tracks help context information like help topic, help category14 /// and help file, which are usually not available when an error happens at15 /// down level.16 ///17 /// Following is how this class can be used.18 ///19 /// using(HelpErrorTracer.Trace(helpTopic, helpCategory, helpFile))20 /// {21 /// InsideFunctionCall();22 /// }23 ///24 /// At this moment, a TraceFrame instance, which is disposable, will be created.25 ///26 /// In inside function calls and the calls down on the call stack, error can27 /// be traced by calling,28 ///29 /// HelpErrorTracer.TraceError(errorRecord)30 ///31 /// At this moment, the errorRecord will be temporarily stored with in TraceFrame instance.32 ///33 /// When the TraceFrame instance is disposed, all errorRecords stored will be34 /// dumped into HelpSystem.LastErrors with context information attached.35 /// </summary>36 internal class HelpErrorTracer37 {38 /// <summary>39 /// TraceFrame class track basic context information for current help activity.40 ///41 /// TraceFrame instance exists in a scope governed by using statement. It is possible42 /// that a new TraceFrame instance will be created in the scope of another TraceFrame43 /// instance. The scopes of various live TraceFrame instances form a stack which is44 /// similar to call stacks of normal C# functions. This is why we call this class45 /// a "TraceFrame"46 ///47 /// TraceFrame itself implements IDisposable interface to guarantee a chance to48 /// write errors into system error pool when execution gets out of its scope. During49 /// disposal time, errorRecords accumulated will be written to system error pool50 /// together with error context information collected at instance creation.51 /// </summary>52 internal sealed class TraceFrame : IDisposable53 {54 // Following are help context information55 private readonly string _helpFile = string.Empty;56 57 // ErrorRecords accumulated during the help content loading.58 private readonly Collection<ErrorRecord> _errors = new Collection<ErrorRecord>();59 60 private readonly HelpErrorTracer _helpTracer;61 /// <summary>62 /// Constructor. Here help context information will be collected.63 /// </summary>64 /// <param name="helpTracer"></param>65 /// <param name="helpFile"></param>66 internal TraceFrame(HelpErrorTracer helpTracer, string helpFile)67 {68 _helpTracer = helpTracer;69 _helpFile = helpFile;70 }71 72 /// <summary>73 /// This is a interface for code in trace frame scope to add errorRecord into74 /// accumulative error pool.75 /// </summary>76 /// <param name="errorRecord"></param>77 internal void TraceError(ErrorRecord errorRecord)78 {79 if (_helpTracer.HelpSystem.VerboseHelpErrors)80 _errors.Add(errorRecord);81 }82 83 /// <summary>84 /// This is a interface for code in trace frame scope to add errorRecord's into85 /// accumulative error pool.86 /// </summary>87 /// <param name="errorRecords"></param>88 internal void TraceErrors(Collection<ErrorRecord> errorRecords)89 {90 if (_helpTracer.HelpSystem.VerboseHelpErrors)91 {92 foreach (ErrorRecord errorRecord in errorRecords)93 {94 _errors.Add(errorRecord);95 }96 }97 }98 99 /// <summary>100 /// This is where we dump ErrorRecord's accumulated to help system error pool101 /// together with some context information.102 /// </summary>103 public void Dispose()104 {105 if (_helpTracer.HelpSystem.VerboseHelpErrors && _errors.Count > 0)106 {107 ErrorRecord errorRecord = new ErrorRecord(new ParentContainsErrorRecordException("Help Load Error"), "HelpLoadError", ErrorCategory.SyntaxError, null);108 errorRecord.ErrorDetails = new ErrorDetails(typeof(HelpErrorTracer).Assembly, "HelpErrors", "HelpLoadError", _helpFile, _errors.Count);109 _helpTracer.HelpSystem.LastErrors.Add(errorRecord);110 111 foreach (ErrorRecord error in _errors)112 {113 _helpTracer.HelpSystem.LastErrors.Add(error);114 }115 }116 117 _helpTracer.PopFrame(this);118 }119 }120 121 internal HelpSystem HelpSystem { get; }122 123 internal HelpErrorTracer(HelpSystem helpSystem)124 {125 if (helpSystem == null)126 {127 throw PSTraceSource.NewArgumentNullException("HelpSystem");128 }129 130 HelpSystem = helpSystem;131 }132 133 /// <summary>134 /// This tracks all live TraceFrame objects, which forms a stack.135 /// </summary>136 private readonly List<TraceFrame> _traceFrames = new List<TraceFrame>();137 138 /// <summary>139 /// This is the API to use for starting a help trace scope.140 /// </summary>141 /// <param name="helpFile"></param>142 /// <returns></returns>143 internal IDisposable Trace(string helpFile)144 {145 TraceFrame traceFrame = new TraceFrame(this, helpFile);146 147 _traceFrames.Add(traceFrame);148 149 return traceFrame;150 }151 152 /// <summary>153 /// This is the api function used for adding errorRecords to TraceFrame's error154 /// pool.155 /// </summary>156 /// <param name="errorRecord"></param>157 internal void TraceError(ErrorRecord errorRecord)158 {159 if (_traceFrames.Count == 0)160 return;161 162 TraceFrame traceFrame = _traceFrames[_traceFrames.Count - 1];163 164 traceFrame.TraceError(errorRecord);165 }166 167 /// <summary>168 /// This is the api function used for adding errorRecords to TraceFrame's error169 /// pool.170 /// </summary>171 /// <param name="errorRecords"></param>172 internal void TraceErrors(Collection<ErrorRecord> errorRecords)173 {174 if (_traceFrames.Count == 0)175 return;176 177 TraceFrame traceFrame = _traceFrames[_traceFrames.Count - 1];178 179 traceFrame.TraceErrors(errorRecords);180 }181 182 internal void PopFrame(TraceFrame traceFrame)183 {184 if (_traceFrames.Count == 0)185 return;186 187 TraceFrame lastFrame = _traceFrames[_traceFrames.Count - 1];188 189 if (lastFrame == traceFrame)190 {191 _traceFrames.RemoveAt(_traceFrames.Count - 1);192 }193 }194 195 /// <summary>196 /// Track whether help error tracer is turned on.197 /// </summary>198 /// <value></value>199 internal bool IsOn200 {201 get202 {203 return (_traceFrames.Count > 0 && this.HelpSystem.VerboseHelpErrors);204 }205 }206 }207}208 