From d5226954fa766df919e52db652c319e5c797efe1 Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Thu, 12 May 2022 16:36:47 -0700 Subject: [PATCH 1/2] Fix the error message in hashtable-to-object conversion --- .../engine/LanguagePrimitives.cs | 19 +++++++++----- .../resources/ExtendedTypeSystem.resx | 5 +++- ...htableToPSCustomObjectConversion.Tests.ps1 | 26 +++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index 3176fbbead1..b697e8e750f 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -310,9 +310,11 @@ public static class LanguagePrimitives internal static void CreateMemberNotFoundError(PSObject pso, DictionaryEntry property, Type resultType) { - string availableProperties = GetAvailableProperties(pso); + string settableProperties = GetSettableProperties(pso); - string message = StringUtil.Format(ExtendedTypeSystem.PropertyNotFound, property.Key.ToString(), resultType.FullName, availableProperties); + string message = settableProperties == string.Empty + ? StringUtil.Format(ExtendedTypeSystem.NoSettableProperty, property.Key.ToString(), resultType.FullName) + : StringUtil.Format(ExtendedTypeSystem.PropertyNotFound, property.Key.ToString(), resultType.FullName, settableProperties); typeConversion.WriteLine("Issuing an error message about not being able to create an object from hashtable."); throw new InvalidOperationException(message); @@ -4735,18 +4737,23 @@ internal static PSObject SetObjectProperties(object o, IDictionary properties, T return pso; } - private static string GetAvailableProperties(PSObject pso) + private static string GetSettableProperties(PSObject pso) { + if (pso is null || pso.Properties is null) + { + return string.Empty; + } + StringBuilder availableProperties = new StringBuilder(); bool first = true; - if (pso != null && pso.Properties != null) + foreach (PSPropertyInfo p in pso.Properties) { - foreach (PSPropertyInfo p in pso.Properties) + if (p.IsSettable) { if (!first) { - availableProperties.Append(" , "); + availableProperties.Append(", "); } availableProperties.Append("[" + p.Name + " <" + p.TypeNameOfValue + ">]"); diff --git a/src/System.Management.Automation/resources/ExtendedTypeSystem.resx b/src/System.Management.Automation/resources/ExtendedTypeSystem.resx index 86b3f826324..3a84b103102 100644 --- a/src/System.Management.Automation/resources/ExtendedTypeSystem.resx +++ b/src/System.Management.Automation/resources/ExtendedTypeSystem.resx @@ -352,7 +352,10 @@ "{0}" returned a null value. - The {0} property was not found for the {1} object. The available property is: {2} + The property '{0}' was not found for the '{1}' object. The settable properties are: {2}. + + + The property '{0}' was not found for the '{1}' object. There is no settable property available. Cannot create object of type "{0}". {1} diff --git a/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 b/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 index 09570e0e1e9..d0fecf33699 100644 --- a/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 +++ b/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 @@ -142,3 +142,29 @@ Describe "Tests for hashtable to PSCustomObject conversion" -Tags "CI" { } } +Describe "Error message with settable Property information" { + BeforeAll { + Add-Type @" +namespace HashtableConversionTest { + public class AType { + public string Name; + public string Path { get; set; } + public string Id { get; } + } +} +"@ + } + + It "Only settable properties are called out in the error message" { + try { + [HashtableConversionTest.AType]@{ key = 1 } + } catch { + $e = $_ + } + + $e.FullyQualifiedErrorId | Should -BeExactly "ObjectCreationError" + $e.Exception.Message.Contains("Name") | Should -BeTrue + $e.Exception.Message.Contains("Path") | Should -BeTrue + $e.Exception.Message.Contains("Id") | Should -BeFalse + } +} From c6cc22d052abf63c749a3458bddc921d97c6a58c Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Mon, 16 May 2022 11:52:48 -0700 Subject: [PATCH 2/2] Address Steve's comment --- .../HashtableToPSCustomObjectConversion.Tests.ps1 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 b/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 index d0fecf33699..8d0d1ac24fe 100644 --- a/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 +++ b/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 @@ -163,8 +163,23 @@ namespace HashtableConversionTest { } $e.FullyQualifiedErrorId | Should -BeExactly "ObjectCreationError" + $e.Exception.Message.Contains("key") | Should -BeTrue $e.Exception.Message.Contains("Name") | Should -BeTrue $e.Exception.Message.Contains("Path") | Should -BeTrue $e.Exception.Message.Contains("Id") | Should -BeFalse } + + It "Shows no property when there is no settable property" { + try { + [System.Collections.Specialized.OrderedDictionary]@{ key = 1 } + } catch { + $e = $_ + } + + $type = [psobject].Assembly.GetType("ExtendedTypeSystem") + $property = $type.GetProperty("NoSettableProperty", @("NonPublic", "Static")) + $resString = $property.GetValue($null) -f 'key', 'System.Collections.Specialized.OrderedDictionary' + + $e.Exception.Message | Should -BeLike "*$resString" + } }