Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
FormatViewGenerator.cs503 linesDownload Raw Back to common
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Linq;6using System.Collections.ObjectModel;7using System.Management.Automation;8using System.Management.Automation.Internal;9 10namespace Microsoft.PowerShell.Commands.Internal.Format11{12    /// <summary>13    /// Base class for the various types of formatting shapes.14    /// </summary>15    internal abstract class ViewGenerator16    {17        internal virtual void Initialize(TerminatingErrorContext terminatingErrorContext,18                                        PSPropertyExpressionFactory mshExpressionFactory,19                                        TypeInfoDataBase db,20                                        ViewDefinition view,21                                        FormattingCommandLineParameters formatParameters)22        {23            Diagnostics.Assert(mshExpressionFactory != null, "mshExpressionFactory cannot be null");24            Diagnostics.Assert(db != null, "db cannot be null");25            Diagnostics.Assert(view != null, "view cannot be null");26 27            errorContext = terminatingErrorContext;28            expressionFactory = mshExpressionFactory;29            parameters = formatParameters;30 31            dataBaseInfo.db = db;32            dataBaseInfo.view = view;33            dataBaseInfo.applicableTypes = DisplayDataQuery.GetAllApplicableTypes(db, view.appliesTo);34 35            InitializeHelper();36        }37 38        internal virtual void Initialize(TerminatingErrorContext terminatingErrorContext,39                                            PSPropertyExpressionFactory mshExpressionFactory,40                                            PSObject so,41                                            TypeInfoDataBase db,42                                            FormattingCommandLineParameters formatParameters)43        {44            errorContext = terminatingErrorContext;45            expressionFactory = mshExpressionFactory;46            parameters = formatParameters;47            dataBaseInfo.db = db;48 49            InitializeHelper();50        }51 52        /// <summary>53        /// Let the view prepare itself for RemoteObjects. Specific view generators can54        /// use this call to customize display for remote objects like showing/hiding55        /// computername property etc.56        /// </summary>57        /// <param name="so"></param>58        internal virtual void PrepareForRemoteObjects(PSObject so)59        {60        }61 62        private void InitializeHelper()63        {64            InitializeFormatErrorManager();65            InitializeGroupBy();66            InitializeAutoSize();67            InitializeRepeatHeader();68        }69 70        private void InitializeFormatErrorManager()71        {72            FormatErrorPolicy formatErrorPolicy = new FormatErrorPolicy();73            if (parameters != null && parameters.showErrorsAsMessages.HasValue)74            {75                formatErrorPolicy.ShowErrorsAsMessages = parameters.showErrorsAsMessages.Value;76            }77            else78            {79                formatErrorPolicy.ShowErrorsAsMessages = this.dataBaseInfo.db.defaultSettingsSection.formatErrorPolicy.ShowErrorsAsMessages;80            }81 82            if (parameters != null && parameters.showErrorsInFormattedOutput.HasValue)83            {84                formatErrorPolicy.ShowErrorsInFormattedOutput = parameters.showErrorsInFormattedOutput.Value;85            }86            else87            {88                formatErrorPolicy.ShowErrorsInFormattedOutput = this.dataBaseInfo.db.defaultSettingsSection.formatErrorPolicy.ShowErrorsInFormattedOutput;89            }90 91            _errorManager = new FormatErrorManager(formatErrorPolicy);92        }93 94        private void InitializeGroupBy()95        {96            // first check if there is an override from the command line97            if (parameters != null && parameters.groupByParameter != null)98            {99                // get the expression to use100                PSPropertyExpression groupingKeyExpression = parameters.groupByParameter.GetEntry(FormatParameterDefinitionKeys.ExpressionEntryKey) as PSPropertyExpression;101 102                // set the label103                string label = null;104                object labelKey = parameters.groupByParameter.GetEntry(FormatParameterDefinitionKeys.LabelEntryKey);105                if (labelKey != AutomationNull.Value)106                {107                    label = labelKey as string;108                }109 110                _groupingManager = new GroupingInfoManager();111                _groupingManager.Initialize(groupingKeyExpression, label);112                return;113            }114 115            // check if we have a view to initialize from116            if (this.dataBaseInfo.view != null)117            {118                GroupBy gb = this.dataBaseInfo.view.groupBy;119                if (gb == null)120                {121                    return;122                }123 124                if (gb.startGroup == null || gb.startGroup.expression == null)125                {126                    return;127                }128 129                PSPropertyExpression ex = this.expressionFactory.CreateFromExpressionToken(gb.startGroup.expression, this.dataBaseInfo.view.loadingInfo);130 131                _groupingManager = new GroupingInfoManager();132                _groupingManager.Initialize(ex, null);133            }134        }135 136        private void InitializeAutoSize()137        {138            // check the autosize flag first139            if (parameters != null && parameters.autosize.HasValue)140            {141                _autosize = parameters.autosize.Value;142                return;143            }144            // check if we have a view with autosize checked145            if (this.dataBaseInfo.view != null && this.dataBaseInfo.view.mainControl != null146                && this.dataBaseInfo.view.mainControl is ControlBody controlBody && controlBody.autosize.HasValue)147            {148                _autosize = controlBody.autosize.Value;149            }150        }151 152        private void InitializeRepeatHeader()153        {154            if (parameters != null)155            {156                _repeatHeader = parameters.repeatHeader;157            }158        }159 160        internal virtual FormatStartData GenerateStartData(PSObject so)161        {162            FormatStartData startFormat = new FormatStartData();163 164            if (_autosize)165            {166                startFormat.autosizeInfo = new AutosizeInfo();167            }168 169            return startFormat;170        }171 172        internal abstract FormatEntryData GeneratePayload(PSObject so, int enumerationLimit);173 174        internal GroupStartData GenerateGroupStartData(PSObject firstObjectInGroup, int enumerationLimit)175        {176            GroupStartData startGroup = new GroupStartData();177            if (_groupingManager == null)178                return startGroup;179 180            object currentGroupingValue = _groupingManager.CurrentGroupingKeyPropertyValue;181 182            if (currentGroupingValue == AutomationNull.Value)183                return startGroup;184 185            PSObject so = PSObjectHelper.AsPSObject(currentGroupingValue);186 187            // we need to determine how to display the group header188            ControlBase control = null;189            TextToken labelTextToken = null;190            if (this.dataBaseInfo.view != null && this.dataBaseInfo.view.groupBy != null)191            {192                if (this.dataBaseInfo.view.groupBy.startGroup != null)193                {194                    // NOTE: from the database constraints, only one of the195                    // two will be non null196                    control = this.dataBaseInfo.view.groupBy.startGroup.control;197                    labelTextToken = this.dataBaseInfo.view.groupBy.startGroup.labelTextToken;198                }199            }200 201            startGroup.groupingEntry = new GroupingEntry();202 203            if (control == null)204            {205                // we do not have a control, we auto generate a206                // snippet of complex display using a label207 208                StringFormatError formatErrorObject = null;209                if (_errorManager.DisplayFormatErrorString)210                {211                    // we send a format error object down to the formatting calls212                    // only if we want to show the formatting error strings213                    formatErrorObject = new StringFormatError();214                }215 216                string currentGroupingValueDisplay = PSObjectHelper.SmartToString(so, this.expressionFactory, enumerationLimit, formatErrorObject);217 218                if (formatErrorObject != null && formatErrorObject.exception != null)219                {220                    // if we did not have any errors in the expression evaluation221                    // we might have errors in the formatting, if present222                    _errorManager.LogStringFormatError(formatErrorObject);223                    if (_errorManager.DisplayFormatErrorString)224                    {225                        currentGroupingValueDisplay = _errorManager.FormatErrorString;226                    }227                }228 229                FormatEntry fe = new FormatEntry();230                startGroup.groupingEntry.formatValueList.Add(fe);231 232                FormatTextField ftf = new FormatTextField();233 234                // determine what the label should be. If we have a label from the235                // database, let's use it, else fall back to the string provided236                // by the grouping manager237                string label;238                if (labelTextToken != null)239                    label = this.dataBaseInfo.db.displayResourceManagerCache.GetTextTokenString(labelTextToken);240                else241                    label = _groupingManager.GroupingKeyDisplayName;242 243                ftf.text = StringUtil.Format(FormatAndOut_format_xxx.GroupStartDataIndentedAutoGeneratedLabel, label);244 245                fe.formatValueList.Add(ftf);246 247                FormatPropertyField fpf = new FormatPropertyField();248 249                fpf.propertyValue = currentGroupingValueDisplay;250                fe.formatValueList.Add(fpf);251            }252            else253            {254                // NOTE: we set a max depth to protect ourselves from infinite loops255                const int maxTreeDepth = 50;256                ComplexControlGenerator controlGenerator =257                                new ComplexControlGenerator(this.dataBaseInfo.db,258                                        this.dataBaseInfo.view.loadingInfo,259                                        this.expressionFactory,260                                        this.dataBaseInfo.view.formatControlDefinitionHolder.controlDefinitionList,261                                        this.ErrorManager,262                                        enumerationLimit,263                                        this.errorContext);264 265                controlGenerator.GenerateFormatEntries(maxTreeDepth,266                    control, firstObjectInGroup, startGroup.groupingEntry.formatValueList);267            }268 269            return startGroup;270        }271 272        /// <summary>273        /// Update the current value of the grouping key.274        /// </summary>275        /// <param name="so">Object to use for the update.</param>276        /// <returns>True if the value of the key changed.</returns>277        internal bool UpdateGroupingKeyValue(PSObject so)278        {279            if (_groupingManager == null)280                return false;281            return _groupingManager.UpdateGroupingKeyValue(so);282        }283 284        internal GroupEndData GenerateGroupEndData()285        {286            return new GroupEndData();287        }288 289        internal bool IsObjectApplicable(Collection<string> typeNames)290        {291            if (dataBaseInfo.view == null)292                return true;293 294            if (typeNames.Count == 0)295                return false;296 297            TypeMatch match = new TypeMatch(expressionFactory, dataBaseInfo.db, typeNames);298            if (match.PerfectMatch(new TypeMatchItem(this, dataBaseInfo.applicableTypes)))299            {300                return true;301            }302 303            bool result = match.BestMatch != null;304 305            // we were unable to find a best match so far..try306            // to get rid of Deserialization prefix and see if a307            // match can be found.308            if (!result)309            {310                Collection<string> typesWithoutPrefix = Deserializer.MaskDeserializationPrefix(typeNames);311                if (typesWithoutPrefix != null)312                {313                    result = IsObjectApplicable(typesWithoutPrefix);314                }315            }316 317            return result;318        }319 320        private GroupingInfoManager _groupingManager = null;321 322        protected bool AutoSize323        {324            get { return _autosize; }325        }326 327        private bool _autosize = false;328 329        protected bool RepeatHeader330        {331            get { return _repeatHeader; }332        }333 334        private bool _repeatHeader = false;335 336        protected class DataBaseInfo337        {338            internal TypeInfoDataBase db = null;339            internal ViewDefinition view = null;340            internal AppliesTo applicableTypes = null;341        }342 343        protected TerminatingErrorContext errorContext;344 345        protected FormattingCommandLineParameters parameters;346 347        protected PSPropertyExpressionFactory expressionFactory;348 349        protected DataBaseInfo dataBaseInfo = new DataBaseInfo();350 351        /// <summary>352        /// Builds the raw association list for the given object.353        /// Subclasses override this to provide cmdlet-specific property expansion logic.354        /// </summary>355        /// <param name="so">The object to build the association list for.</param>356        /// <param name="propertyList">The list of properties specified by the user, or null if not specified.</param>357        /// <returns>The raw association list, or null if not applicable.</returns>358        protected virtual List<MshResolvedExpressionParameterAssociation> BuildRawAssociationList(PSObject so, List<MshParameter> propertyList)359        {360            return null;361        }362 363        /// <summary>364        /// Builds the active association list for the given object, with ExcludeProperty filter applied.365        /// </summary>366        /// <param name="so">The object to build the association list for.</param>367        /// <returns>The filtered association list.</returns>368        protected List<MshResolvedExpressionParameterAssociation> BuildActiveAssociationList(PSObject so)369        {370            var propertyList = parameters?.mshParameterList;371            var excludeFilter = parameters?.excludePropertyFilter;372            var rawList = BuildRawAssociationList(so, propertyList);373            return ApplyExcludeFilter(rawList, excludeFilter);374        }375 376        /// <summary>377        /// Applies the ExcludeProperty filter to the given association list.378        /// </summary>379        /// <param name="associationList">The list to filter.</param>380        /// <param name="excludeFilter">The exclude filter to apply.</param>381        /// <returns>The filtered list, or the original list if no filter is specified.</returns>382        internal static List<MshResolvedExpressionParameterAssociation> ApplyExcludeFilter(383            List<MshResolvedExpressionParameterAssociation> associationList,384            PSPropertyExpressionFilter excludeFilter)385        {386            if (associationList is null || excludeFilter is null)387            {388                return associationList;389            }390 391            return associationList392                .Where(item => !excludeFilter.IsMatch(item.ResolvedExpression))393                .ToList();394        }395 396        protected string GetExpressionDisplayValue(PSObject so, int enumerationLimit, PSPropertyExpression ex,397                    FieldFormattingDirective directive)398        {399            PSPropertyExpressionResult resolvedExpression;400            return GetExpressionDisplayValue(so, enumerationLimit, ex, directive, out resolvedExpression);401        }402 403        protected string GetExpressionDisplayValue(PSObject so, int enumerationLimit, PSPropertyExpression ex,404                    FieldFormattingDirective directive, out PSPropertyExpressionResult expressionResult)405        {406            StringFormatError formatErrorObject = null;407            if (_errorManager.DisplayFormatErrorString)408            {409                // we send a format error object down to the formatting calls410                // only if we want to show the formatting error strings411                formatErrorObject = new StringFormatError();412            }413 414            string retVal = PSObjectHelper.GetExpressionDisplayValue(so, enumerationLimit, ex,415                                directive, formatErrorObject, expressionFactory, out expressionResult);416 417            if (expressionResult != null)418            {419                // we obtained a result, check if there is an error420                if (expressionResult.Exception != null)421                {422                    _errorManager.LogPSPropertyExpressionFailedResult(expressionResult, so);423                    if (_errorManager.DisplayErrorStrings)424                    {425                        retVal = _errorManager.ErrorString;426                    }427                }428                else if (formatErrorObject != null && formatErrorObject.exception != null)429                {430                    // if we did not have any errors in the expression evaluation431                    // we might have errors in the formatting, if present432                    _errorManager.LogStringFormatError(formatErrorObject);433                    if (_errorManager.DisplayErrorStrings)434                    {435                        retVal = _errorManager.FormatErrorString;436                    }437                }438            }439 440            return retVal;441        }442 443        protected bool EvaluateDisplayCondition(PSObject so, ExpressionToken conditionToken)444        {445            if (conditionToken == null)446                return true;447 448            PSPropertyExpression ex = this.expressionFactory.CreateFromExpressionToken(conditionToken, this.dataBaseInfo.view.loadingInfo);449            PSPropertyExpressionResult expressionResult;450            bool retVal = DisplayCondition.Evaluate(so, ex, out expressionResult);451 452            if (expressionResult != null && expressionResult.Exception != null)453            {454                _errorManager.LogPSPropertyExpressionFailedResult(expressionResult, so);455            }456 457            return retVal;458        }459 460        internal FormatErrorManager ErrorManager461        {462            get { return _errorManager; }463        }464 465        private FormatErrorManager _errorManager;466 467        #region helpers468 469        protected FormatPropertyField GenerateFormatPropertyField(List<FormatToken> formatTokenList, PSObject so, int enumerationLimit)470        {471            PSPropertyExpressionResult result;472            return GenerateFormatPropertyField(formatTokenList, so, enumerationLimit, out result);473        }474 475        protected FormatPropertyField GenerateFormatPropertyField(List<FormatToken> formatTokenList, PSObject so, int enumerationLimit, out PSPropertyExpressionResult result)476        {477            result = null;478            FormatPropertyField fpf = new FormatPropertyField();479            if (formatTokenList.Count != 0)480            {481                FormatToken token = formatTokenList[0];482                if (token is FieldPropertyToken fpt)483                {484                    PSPropertyExpression ex = this.expressionFactory.CreateFromExpressionToken(fpt.expression, this.dataBaseInfo.view.loadingInfo);485                    fpf.propertyValue = this.GetExpressionDisplayValue(so, enumerationLimit, ex, fpt.fieldFormattingDirective, out result);486                }487                else if (token is TextToken tt)488                {489                    fpf.propertyValue = this.dataBaseInfo.db.displayResourceManagerCache.GetTextTokenString(tt);490                }491            }492            else493            {494                fpf.propertyValue = string.Empty;495            }496 497            return fpf;498        }499 500        #endregion501    }502}503