From 41c7cd79da65a3e0c481bdb268fc47c11a46c2fd Mon Sep 17 00:00:00 2001 From: Dongbo Wang Date: Mon, 16 May 2022 14:55:00 -0700 Subject: [PATCH] Fix the error message in Hashtable-to-object conversion (#17329) --- .../engine/LanguagePrimitives.cs | 19 ++++++--- .../resources/ExtendedTypeSystem.resx | 5 ++- ...htableToPSCustomObjectConversion.Tests.ps1 | 41 +++++++++++++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index 3176fbbead..b697e8e750 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -310,9 +310,11 @@ namespace System.Management.Automation 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 @@ namespace System.Management.Automation 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 86b3f82632..3a84b10310 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 09570e0e1e..8d0d1ac24f 100644 --- a/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 +++ b/test/powershell/Language/Scripting/HashtableToPSCustomObjectConversion.Tests.ps1 @@ -142,3 +142,44 @@ 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("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" + } +}