From 074f2a6355be1c922ae428ceafeaec24465927bd Mon Sep 17 00:00:00 2001 From: xtqqczze Date: Sun, 30 Aug 2020 01:35:03 +0100 Subject: [PATCH 1/5] Avoid LINQ Count method --- .../engine/Modules/ImportModuleCommand.cs | 3 +-- .../engine/TypeTable.cs | 15 ++++++++++----- .../help/HelpCommands.cs | 15 +++++---------- test/tools/WebListener/Program.cs | 2 +- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs index f6641930bf7..f6edc8ae2fa 100644 --- a/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs +++ b/src/System.Management.Automation/engine/Modules/ImportModuleCommand.cs @@ -1076,8 +1076,7 @@ private PSModuleInfo ImportModule_RemotelyViaPsrpSession_SinglePreimportedModule CultureInfo.InvariantCulture, Modules.RemoteDiscoveryFailedToGenerateProxyForRemoteModule, remoteModuleName); - int numberOfLocallyCreatedFiles = RemoteDiscoveryHelper.InvokePowerShell(powerShell, this.CancellationToken, this, errorMessageTemplate).Count(); - if (numberOfLocallyCreatedFiles == 0) + if (!RemoteDiscoveryHelper.InvokePowerShell(powerShell, this.CancellationToken, this, errorMessageTemplate).Any()) { return null; } diff --git a/src/System.Management.Automation/engine/TypeTable.cs b/src/System.Management.Automation/engine/TypeTable.cs index 74b2f6910f8..783cce9b1b4 100644 --- a/src/System.Management.Automation/engine/TypeTable.cs +++ b/src/System.Management.Automation/engine/TypeTable.cs @@ -3291,7 +3291,12 @@ private static void AddError(ConcurrentBag errors, string typeName, stri #region add members from TypeData - private static void ProcessMembersData(ConcurrentBag errors, string typeName, IEnumerable membersData, PSMemberInfoInternalCollection membersCollection, bool isOverride) + private static void ProcessMembersData( + ConcurrentBag errors, + string typeName, + Dictionary.ValueCollection membersData, + PSMemberInfoInternalCollection membersCollection, + bool isOverride) { foreach (TypeMemberData typeMember in membersData) { @@ -3449,12 +3454,12 @@ internal static void ProcessMemberSetData(ConcurrentBag errors, string t private static void ProcessStandardMembers( ConcurrentBag errors, string typeName, - IEnumerable standardMembers, - IEnumerable propertySets, + Dictionary.ValueCollection standardMembers, + List propertySets, PSMemberInfoInternalCollection membersCollection, bool isOverride) { - int newMemberCount = standardMembers.Count() + propertySets.Count(); + int newMemberCount = standardMembers.Count + propertySets.Count; // If StandardMembers do not exists, we follow the original logic to create the StandardMembers if (membersCollection[PSStandardMembers] == null) @@ -3679,7 +3684,7 @@ private void ProcessTypeDataToAdd(ConcurrentBag errors, TypeData typeDat string typeName = typeData.TypeName; Dbg.Assert(!string.IsNullOrEmpty(typeName), "TypeData class guarantees the typeName is not null and not empty"); - var propertySets = new Collection(); + var propertySets = new List(); if (typeData.DefaultDisplayPropertySet != null) { propertySets.Add(typeData.DefaultDisplayPropertySet); diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index ca630180fbf..f52a1b0c162 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -864,18 +864,13 @@ private static bool DoesCurrentRunspaceIncludeCoreHelpCmdlet() IEnumerable publicGetHelpEntries = iss .Commands["Get-Help"] .Where(entry => entry.Visibility == SessionStateEntryVisibility.Public); - if (publicGetHelpEntries.Count() != 1) - { - return false; - } - foreach (SessionStateCommandEntry getHelpEntry in publicGetHelpEntries) + using (var en = publicGetHelpEntries.GetEnumerator()) { - SessionStateCmdletEntry getHelpCmdlet = getHelpEntry as SessionStateCmdletEntry; - if ((getHelpCmdlet != null) && (getHelpCmdlet.ImplementingType.Equals(typeof(GetHelpCommand)))) - { - return true; - } + // Returns false if the number of elements is not 1 + return en.MoveNext() + && ((en.Current as SessionStateCmdletEntry)?.ImplementingType.Equals(typeof(GetHelpCommand)) == true) + && !en.MoveNext(); } } diff --git a/test/tools/WebListener/Program.cs b/test/tools/WebListener/Program.cs index 691ef60b7c2..170f59bbe1f 100644 --- a/test/tools/WebListener/Program.cs +++ b/test/tools/WebListener/Program.cs @@ -20,7 +20,7 @@ public class Program { public static void Main(string[] args) { - if (args.Count() != 6) + if (args.Length != 6) { System.Console.WriteLine("Required: "); Environment.Exit(1); From f1b25ee187ab8d1d356b1739bde59f67668aa4e4 Mon Sep 17 00:00:00 2001 From: xtqqczze Date: Thu, 22 Oct 2020 18:41:02 +0100 Subject: [PATCH 2/5] Add additional comments for clarity --- src/System.Management.Automation/help/HelpCommands.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index f52a1b0c162..739af7d7756 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -867,10 +867,10 @@ private static bool DoesCurrentRunspaceIncludeCoreHelpCmdlet() using (var en = publicGetHelpEntries.GetEnumerator()) { - // Returns false if the number of elements is not 1 - return en.MoveNext() - && ((en.Current as SessionStateCmdletEntry)?.ImplementingType.Equals(typeof(GetHelpCommand)) == true) - && !en.MoveNext(); + // Return true when there is exactly one element and that element has an implementing type of GetHelpCommand. + return en.MoveNext() // cardinality 0 + && ((en.Current as SessionStateCmdletEntry)?.ImplementingType.Equals(typeof(GetHelpCommand)) == true) // cardinality 1 + && !en.MoveNext(); // cardinality 2..* } } From 3b2c5a3b108590302b0543923c016e6b4686629d Mon Sep 17 00:00:00 2001 From: xtqqczze Date: Thu, 22 Oct 2020 23:00:21 +0100 Subject: [PATCH 3/5] Extract use of IEnumerator to TrySingle --- .../help/HelpCommands.cs | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index 0a5992743d4..e9e564beeef 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -733,30 +733,44 @@ internal static void VerifyParameterForbiddenInRemoteRunspace(Cmdlet cmdlet, str /// public static class GetHelpCodeMethods { + private static bool TrySingle(IEnumerable source, out TSource element) + { + using (IEnumerator e = source.GetEnumerator()) + { + if (e.MoveNext()) + { + TSource result = e.Current; + if (!e.MoveNext()) + { + element = result; + return true; + } + } + } + + element = default; + return false; + } + /// /// Verifies if the InitialSessionState of the current process. /// /// private static bool DoesCurrentRunspaceIncludeCoreHelpCmdlet() { - InitialSessionState iss = - System.Management.Automation.Runspaces.Runspace.DefaultRunspace.InitialSessionState; - if (iss != null) + InitialSessionState iss = Runspace.DefaultRunspace.InitialSessionState; + if (iss is null) { - IEnumerable publicGetHelpEntries = iss - .Commands["Get-Help"] - .Where(entry => entry.Visibility == SessionStateEntryVisibility.Public); - - using (var en = publicGetHelpEntries.GetEnumerator()) - { - // Return true when there is exactly one element and that element has an implementing type of GetHelpCommand. - return en.MoveNext() // cardinality 0 - && ((en.Current as SessionStateCmdletEntry)?.ImplementingType.Equals(typeof(GetHelpCommand)) == true) // cardinality 1 - && !en.MoveNext(); // cardinality 2..* - } + return false; } - return false; + IEnumerable publicGetHelpEntries = iss + .Commands["Get-Help"] + .Where(entry => entry.Visibility == SessionStateEntryVisibility.Public); + + return TrySingle(publicGetHelpEntries, out SessionStateCommandEntry entry) + && entry is SessionStateCmdletEntry getHelpCmdlet + && getHelpCmdlet.ImplementingType.Equals(typeof(GetHelpCommand)); } /// From 6805e0d75b6d9bbac6d27e3877ccaa4210d423cb Mon Sep 17 00:00:00 2001 From: xtqqczze Date: Thu, 22 Oct 2020 23:20:24 +0100 Subject: [PATCH 4/5] Address @rjmholt review --- src/System.Management.Automation/engine/TypeTable.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/System.Management.Automation/engine/TypeTable.cs b/src/System.Management.Automation/engine/TypeTable.cs index d6fc98372b6..b05e7f1c1c2 100644 --- a/src/System.Management.Automation/engine/TypeTable.cs +++ b/src/System.Management.Automation/engine/TypeTable.cs @@ -3293,11 +3293,11 @@ private static void AddError(ConcurrentBag errors, string typeName, stri private static void ProcessMembersData( ConcurrentBag errors, string typeName, - Dictionary.ValueCollection membersData, + Dictionary membersData, PSMemberInfoInternalCollection membersCollection, bool isOverride) { - foreach (TypeMemberData typeMember in membersData) + foreach (TypeMemberData typeMember in membersData.Values) { typeMember.Process(errors, typeName, membersCollection, isOverride); } @@ -3453,7 +3453,7 @@ internal static void ProcessMemberSetData(ConcurrentBag errors, string t private static void ProcessStandardMembers( ConcurrentBag errors, string typeName, - Dictionary.ValueCollection standardMembers, + Dictionary standardMembers, List propertySets, PSMemberInfoInternalCollection membersCollection, bool isOverride) @@ -3714,7 +3714,7 @@ private void ProcessTypeDataToAdd(ConcurrentBag errors, TypeData typeDat if (typeData.Members.Count > 0) { typeMembers = _extendedMembers.GetOrAdd(typeName, GetValueFactoryBasedOnInitCapacity(collectionSize)); - ProcessMembersData(errors, typeName, typeData.Members.Values, typeMembers, typeData.IsOverride); + ProcessMembersData(errors, typeName, typeData.Members, typeMembers, typeData.IsOverride); foreach (var memberName in typeData.Members.Keys) { @@ -3729,7 +3729,7 @@ private void ProcessTypeDataToAdd(ConcurrentBag errors, TypeData typeDat typeMembers = _extendedMembers.GetOrAdd(typeName, GetValueFactoryBasedOnInitCapacity(capacity: 1)); } - ProcessStandardMembers(errors, typeName, typeData.StandardMembers.Values, propertySets, typeMembers, typeData.IsOverride); + ProcessStandardMembers(errors, typeName, typeData.StandardMembers, propertySets, typeMembers, typeData.IsOverride); } if (typeData.TypeConverter != null) From 396e3563560a0eeba50859cabc12ebfb8a94ffc1 Mon Sep 17 00:00:00 2001 From: xtqqczze Date: Mon, 2 Nov 2020 02:29:37 +0000 Subject: [PATCH 5/5] Refactor DoesCurrentRunspaceIncludeCoreHelpCmdlet Address @rjmholt review Co-Authored-By: Robert Holt --- .../help/HelpCommands.cs | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index e9e564beeef..994a8be1ac9 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -733,29 +733,10 @@ internal static void VerifyParameterForbiddenInRemoteRunspace(Cmdlet cmdlet, str /// public static class GetHelpCodeMethods { - private static bool TrySingle(IEnumerable source, out TSource element) - { - using (IEnumerator e = source.GetEnumerator()) - { - if (e.MoveNext()) - { - TSource result = e.Current; - if (!e.MoveNext()) - { - element = result; - return true; - } - } - } - - element = default; - return false; - } - /// - /// Verifies if the InitialSessionState of the current process. - /// - /// + /// Checks whether the default runspace associated with the current thread has the standard Get-Help cmdlet. + /// + /// True if Get-Help is found, false otherwise. private static bool DoesCurrentRunspaceIncludeCoreHelpCmdlet() { InitialSessionState iss = Runspace.DefaultRunspace.InitialSessionState; @@ -764,13 +745,27 @@ private static bool DoesCurrentRunspaceIncludeCoreHelpCmdlet() return false; } - IEnumerable publicGetHelpEntries = iss - .Commands["Get-Help"] - .Where(entry => entry.Visibility == SessionStateEntryVisibility.Public); + Collection getHelpEntries = iss.Commands["Get-Help"]; + SessionStateCommandEntry getHelpEntry = null; + for (int i = 0; i < getHelpEntries.Count; ++i) + { + if (getHelpEntries[i].Visibility is not SessionStateEntryVisibility.Public) + { + continue; + } + + // If we have multiple entries for Get-Help, + // our assumption is that the standard Get-Help is not available. + if (getHelpEntry is not null) + { + return false; + } + + getHelpEntry = getHelpEntries[i]; + } - return TrySingle(publicGetHelpEntries, out SessionStateCommandEntry entry) - && entry is SessionStateCmdletEntry getHelpCmdlet - && getHelpCmdlet.ImplementingType.Equals(typeof(GetHelpCommand)); + return getHelpEntry is SessionStateCmdletEntry getHelpCmdlet + && getHelpCmdlet.ImplementingType == typeof(GetHelpCommand); } ///