Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -348,19 +348,49 @@ protected class DataBaseInfo

protected DataBaseInfo dataBaseInfo = new DataBaseInfo();

protected List<MshResolvedExpressionParameterAssociation> activeAssociationList = null;
/// <summary>
/// Apply ExcludeProperty filter to activeAssociationList if specified.
/// This method filters and updates "activeAssociationList" instance property.
/// Builds the raw association list for the given object.
/// Subclasses override this to provide cmdlet-specific property expansion logic.
/// </summary>
protected void ApplyExcludePropertyFilter()
/// <param name="so">The object to build the association list for.</param>
/// <param name="propertyList">The list of properties specified by the user, or null if not specified.</param>
/// <returns>The raw association list, or null if not applicable.</returns>
protected virtual List<MshResolvedExpressionParameterAssociation> BuildRawAssociationList(PSObject so, List<MshParameter> propertyList)
{
if (this.parameters is not null && this.parameters.excludePropertyFilter is not null)
return null;
}

/// <summary>
/// Builds the active association list for the given object, with ExcludeProperty filter applied.
/// </summary>
/// <param name="so">The object to build the association list for.</param>
/// <returns>The filtered association list.</returns>
protected List<MshResolvedExpressionParameterAssociation> BuildActiveAssociationList(PSObject so)
{
var propertyList = parameters?.mshParameterList;
var excludeFilter = parameters?.excludePropertyFilter;
var rawList = BuildRawAssociationList(so, propertyList);
Comment on lines +370 to +372
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace var-s with real type.

return ApplyExcludeFilter(rawList, excludeFilter);
}

/// <summary>
/// Applies the ExcludeProperty filter to the given association list.
/// </summary>
/// <param name="associationList">The list to filter.</param>
/// <param name="excludeFilter">The exclude filter to apply.</param>
/// <returns>The filtered list, or the original list if no filter is specified.</returns>
internal static List<MshResolvedExpressionParameterAssociation> ApplyExcludeFilter(
List<MshResolvedExpressionParameterAssociation> associationList,
PSPropertyExpressionFilter excludeFilter)
{
if (associationList is null || excludeFilter is null)
{
this.activeAssociationList = this.activeAssociationList
.Where(item => !this.parameters.excludePropertyFilter.IsMatch(item.ResolvedExpression))
.ToList();
return associationList;
}

return associationList
.Where(item => !excludeFilter.IsMatch(item.ResolvedExpression))
.ToList();
}

protected string GetExpressionDisplayValue(PSObject so, int enumerationLimit, PSPropertyExpression ex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Internal;
Expand Down Expand Up @@ -514,13 +513,8 @@ private void DisplayObject(PSObject so, TraversalInfo currentLevel, List<MshPara
List<MshResolvedExpressionParameterAssociation> activeAssociationList =
AssociationManager.SetupActiveProperties(parameterList, so, _expressionFactory);

// Apply ExcludeProperty filter if specified
if (_parameters != null && _parameters.excludePropertyFilter != null)
{
activeAssociationList = activeAssociationList
.Where(item => !_parameters.excludePropertyFilter.IsMatch(item.ResolvedExpression))
.ToList();
}
// Apply ExcludeProperty filter using the centralized method
activeAssociationList = ViewGenerator.ApplyExcludeFilter(activeAssociationList, _parameters?.excludePropertyFilter);
Comment on lines +516 to +517
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect we benefit from streaming here too. I mean something like - if we set arguments in constructor and SetupActiveProperties we can get filtered list with ActiveAssociationList property.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion.

Could you clarify the design you have in mind? I want to make sure I understand correctly.

Currently, ComplexViewObjectBrowser is an independent class (not inheriting from ViewGenerator). It processes nested objects by calling DisplayObject recursively - each call handles a different PSObject and creates a new association list via AssociationManager.SetupActiveProperties.

Are you suggesting to:

  • Extend AssociationManager.SetupActiveProperties to accept an optional excludeFilter parameter?
  • Or restructure ComplexViewObjectBrowser to use ViewGenerator's ActiveAssociationList pattern?

Also, replacing this recursive structure with an iterative approach using explicit stack might enable further streaming optimizations, but that would be a larger architectural change. Should I file a separate issue for that?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's worth it. It's better to spend time on something more useful.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback. I'll keep the current implementation.


// create a format entry
FormatEntry fe = new FormatEntry();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ internal override void Initialize(TerminatingErrorContext errorContext, PSProper
{
_listBody = (ListControlBody)this.dataBaseInfo.view.mainControl;
}
}

this.parameters = parameters;
SetUpActiveProperties(so);
/// <summary>
/// Builds the raw association list for list formatting.
/// </summary>
protected override List<MshResolvedExpressionParameterAssociation> BuildRawAssociationList(PSObject so, List<MshParameter> propertyList)
{
return AssociationManager.SetupActiveProperties(propertyList, so, this.expressionFactory);
}
Comment thread
iSazonov marked this conversation as resolved.

/// <summary>
Expand Down Expand Up @@ -178,17 +183,14 @@ private ListControlEntryDefinition GetActiveListControlEntryDefinition(ListContr

private ListViewEntry GenerateListViewEntryFromProperties(PSObject so, int enumerationLimit)
{
// compute active properties every time
if (this.activeAssociationList == null)
{
SetUpActiveProperties(so);
}
// Build active association list (with ExcludeProperty filter applied)
var associationList = BuildActiveAssociationList(so);

ListViewEntry lve = new ListViewEntry();

for (int k = 0; k < this.activeAssociationList.Count; k++)
for (int k = 0; k < associationList.Count; k++)
{
MshResolvedExpressionParameterAssociation a = this.activeAssociationList[k];
MshResolvedExpressionParameterAssociation a = associationList[k];
ListViewField lvf = new ListViewField();

if (a.OriginatingParameter != null)
Expand Down Expand Up @@ -218,21 +220,7 @@ private ListViewEntry GenerateListViewEntryFromProperties(PSObject so, int enume
lvf.formatPropertyField.propertyValue = this.GetExpressionDisplayValue(so, enumerationLimit, a.ResolvedExpression, directive);
lve.listViewFieldList.Add(lvf);
}

this.activeAssociationList = null;
return lve;
}

private void SetUpActiveProperties(PSObject so)
{
List<MshParameter> mshParameterList = null;

if (this.parameters != null)
mshParameterList = this.parameters.mshParameterList;

this.activeAssociationList = AssociationManager.SetupActiveProperties(mshParameterList, so, this.expressionFactory);

ApplyExcludePropertyFilter();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ internal sealed class TableViewGenerator : ViewGenerator
// tableBody to use for this instance of the ViewGenerator;
private TableControlBody _tableBody;

private List<MshResolvedExpressionParameterAssociation> _activeAssociationList;

internal override void Initialize(TerminatingErrorContext terminatingErrorContext, PSPropertyExpressionFactory mshExpressionFactory, TypeInfoDataBase db, ViewDefinition view, FormattingCommandLineParameters formatParameters)
{
base.Initialize(terminatingErrorContext, mshExpressionFactory, db, view, formatParameters);
Expand All @@ -34,51 +36,48 @@ internal override void Initialize(TerminatingErrorContext errorContext, PSProper
_tableBody = (TableControlBody)this.dataBaseInfo.view.mainControl;
}

List<MshParameter> rawMshParameterList = null;

if (parameters != null)
rawMshParameterList = parameters.mshParameterList;
// Build the active association list (with ExcludeProperty filter applied)
_activeAssociationList = BuildActiveAssociationList(so);
}

/// <summary>
/// Builds the raw association list for table formatting.
/// </summary>
protected override List<MshResolvedExpressionParameterAssociation> BuildRawAssociationList(PSObject so, List<MshParameter> propertyList)
{
// check if we received properties from the command line
if (rawMshParameterList is not null && rawMshParameterList.Count > 0)
if (propertyList is not null && propertyList.Count > 0)
{
this.activeAssociationList = AssociationManager.ExpandTableParameters(rawMshParameterList, so);
return AssociationManager.ExpandTableParameters(propertyList, so);
}
else

// we did not get any properties:
// try to get properties from the default property set of the object
var list = AssociationManager.ExpandDefaultPropertySet(so, this.expressionFactory);
if (list.Count > 0)
{
// we did not get any properties:
// try to get properties from the default property set of the object
this.activeAssociationList = AssociationManager.ExpandDefaultPropertySet(so, this.expressionFactory);
if (this.activeAssociationList.Count > 0)
{
// we got a valid set of properties from the default property set..add computername for
// remoteobjects (if available)
if (PSObjectHelper.ShouldShowComputerNameProperty(so))
{
activeAssociationList.Add(new MshResolvedExpressionParameterAssociation(null,
new PSPropertyExpression(RemotingConstants.ComputerNameNoteProperty)));
}
}
else
// we got a valid set of properties from the default property set..add computername for
// remoteobjects (if available)
if (PSObjectHelper.ShouldShowComputerNameProperty(so))
{
// we failed to get anything from the default property set
this.activeAssociationList = AssociationManager.ExpandAll(so);
if (this.activeAssociationList.Count > 0)
{
// Remove PSComputerName and PSShowComputerName from the display as needed.
AssociationManager.HandleComputerNameProperties(so, activeAssociationList);
FilterActiveAssociationList();
}
else
{
// we were unable to retrieve any properties, so we leave an empty list
this.activeAssociationList = new List<MshResolvedExpressionParameterAssociation>();
return;
}
list.Add(new MshResolvedExpressionParameterAssociation(null,
new PSPropertyExpression(RemotingConstants.ComputerNameNoteProperty)));
}

return list;
}

ApplyExcludePropertyFilter();
// we failed to get anything from the default property set
list = AssociationManager.ExpandAll(so);
if (list.Count > 0)
{
// Remove PSComputerName and PSShowComputerName from the display as needed.
AssociationManager.HandleComputerNameProperties(so, list);
return LimitAssociationListSize(list);
}

// we were unable to retrieve any properties, so we leave an empty list
return new List<MshResolvedExpressionParameterAssociation>();
}

/// <summary>
Expand Down Expand Up @@ -129,30 +128,29 @@ internal override FormatStartData GenerateStartData(PSObject so)
}

/// <summary>
/// Method to filter resolved expressions as per table view needs.
/// Limits the association list size for table view.
/// For v1.0, table view supports only 10 properties.
///
/// This method filters and updates "activeAssociationList" instance property.
/// </summary>
/// <returns>None.</returns>
/// <remarks>This method updates "activeAssociationList" instance property.</remarks>
private void FilterActiveAssociationList()
/// <param name="list">The list to limit.</param>
/// <returns>The limited list.</returns>
private static List<MshResolvedExpressionParameterAssociation> LimitAssociationListSize(
List<MshResolvedExpressionParameterAssociation> list)
{
// we got a valid set of properties from the default property set
// make sure we do not have too many properties

// NOTE: this is an arbitrary number, chosen to be a sensitive default
const int nMax = 10;
const int maxCount = 10;

if (list.Count <= maxCount)
{
return list;
}

if (activeAssociationList.Count > nMax)
var result = new List<MshResolvedExpressionParameterAssociation>(maxCount);
for (int k = 0; k < maxCount; k++)
{
List<MshResolvedExpressionParameterAssociation> tmp = this.activeAssociationList;
this.activeAssociationList = new List<MshResolvedExpressionParameterAssociation>();
for (int k = 0; k < nMax; k++)
this.activeAssociationList.Add(tmp[k]);
result.Add(list[k]);
}

return;
return result;
}

private TableHeaderInfo GenerateTableHeaderInfoFromDataBaseInfo(PSObject so)
Expand Down Expand Up @@ -228,9 +226,9 @@ private TableHeaderInfo GenerateTableHeaderInfoFromProperties(PSObject so)
thi.hideHeader = this.HideHeaders;
thi.repeatHeader = this.RepeatHeader;

for (int k = 0; k < this.activeAssociationList.Count; k++)
for (int k = 0; k < _activeAssociationList.Count; k++)
{
MshResolvedExpressionParameterAssociation a = this.activeAssociationList[k];
MshResolvedExpressionParameterAssociation a = _activeAssociationList[k];
TableColumnInfo ci = new TableColumnInfo();

// set the label of the column
Expand All @@ -241,7 +239,7 @@ private TableHeaderInfo GenerateTableHeaderInfoFromProperties(PSObject so)
ci.propertyName = (string)key;
}

ci.propertyName ??= this.activeAssociationList[k].ResolvedExpression.ToString();
ci.propertyName ??= _activeAssociationList[k].ResolvedExpression.ToString();

// set the width of the table
if (a.OriginatingParameter != null)
Expand Down Expand Up @@ -473,13 +471,13 @@ private TableRowEntry GenerateTableRowEntryFromDataBaseInfo(PSObject so, int enu
private TableRowEntry GenerateTableRowEntryFromFromProperties(PSObject so, int enumerationLimit)
{
TableRowEntry tre = new TableRowEntry();
for (int k = 0; k < this.activeAssociationList.Count; k++)
for (int k = 0; k < _activeAssociationList.Count; k++)
{
FormatPropertyField fpf = new FormatPropertyField();
FieldFormattingDirective directive = null;
if (activeAssociationList[k].OriginatingParameter != null)
if (_activeAssociationList[k].OriginatingParameter != null)
{
directive = activeAssociationList[k].OriginatingParameter.GetEntry(FormatParameterDefinitionKeys.FormatStringEntryKey) as FieldFormattingDirective;
directive = _activeAssociationList[k].OriginatingParameter.GetEntry(FormatParameterDefinitionKeys.FormatStringEntryKey) as FieldFormattingDirective;
}

if (directive is null)
Expand All @@ -488,7 +486,7 @@ private TableRowEntry GenerateTableRowEntryFromFromProperties(PSObject so, int e
directive.isTable = true;
}

fpf.propertyValue = this.GetExpressionDisplayValue(so, enumerationLimit, this.activeAssociationList[k].ResolvedExpression, directive);
fpf.propertyValue = this.GetExpressionDisplayValue(so, enumerationLimit, _activeAssociationList[k].ResolvedExpression, directive);
tre.formatPropertyFieldList.Add(fpf);
}

Expand Down
Loading
Loading