From 9f960c82c511611202214ebdbd63fbd2f7e364bf Mon Sep 17 00:00:00 2001
From: "Rick Nguyen (from Dev Box)" <ricknguyen@microsoft.com>
Date: Wed, 18 Sep 2024 10:05:21 -0700
Subject: [PATCH 1/6] initial commit

---
 .../AssemblyProperties.cs                     |  1 +
 .../Functions/UserDefinedFunction.cs          | 66 ++++++++++++++++++-
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/src/libraries/Microsoft.PowerFx.Core/AssemblyProperties.cs b/src/libraries/Microsoft.PowerFx.Core/AssemblyProperties.cs
index 5b2f400237..e55c4e2715 100644
--- a/src/libraries/Microsoft.PowerFx.Core/AssemblyProperties.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/AssemblyProperties.cs
@@ -11,6 +11,7 @@
 [assembly: InternalsVisibleTo("DocumentServer, PublicKey=002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3")]
 [assembly: InternalsVisibleTo("DocumentServer.Common.Tests, PublicKey=002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3")]
 [assembly: InternalsVisibleTo("DocumentServer.Core, PublicKey=002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3")]
+[assembly: InternalsVisibleTo("AgentWorker, PublicKey=002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3")]
 [assembly: InternalsVisibleTo("DocumentServer.Tests, PublicKey=002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3")]
 [assembly: InternalsVisibleTo("DocumentServer.Core.Tests, PublicKey=002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3")]
 [assembly: InternalsVisibleTo("DocumentServer.Core.Tests.WithDataflow, PublicKey=002400000c800000140100000602000000240000525341310008000001000100613399aff18ef1a2c2514a273a42d9042b72321f1757102df9ebada69923e2738406c21e5b801552ab8d200a65a235e001ac9adc25f2d811eb09496a4c6a59d4619589c69f5baf0c4179a47311d92555cd006acc8b5959f2bd6e10e360c34537a1d266da8085856583c85d81da7f3ec01ed9564c58d93d713cd0172c8e23a10f0239b80c96b07736f5d8b022542a4e74251a5f432824318b3539a5a087f8e53d2f135f9ca47f3bb2e10aff0af0849504fb7cea3ff192dc8de0edad64c68efde34c56d302ad55fd6e80f302d5efcdeae953658d3452561b5f36c542efdbdd9f888538d374cef106acf7d93a4445c3c73cd911f0571aaf3d54da12b11ddec375b3")]
diff --git a/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs b/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
index 812122724f..9d5b4eb76d 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
@@ -93,6 +93,70 @@ public UserDefinedFunction(string functionName, DType returnType, TexlNode body,
             this.UdfBody = body;
         }
 
+        public UserDefinedFunction(string functionName, DType returnType, TexlNode body, bool isImperative, ISet<UDFArg> args, DType[] argTypes, string description)
+            : base(DPath.Root, functionName, functionName, SG(!string.IsNullOrWhiteSpace(description) ? description : "Using " + functionName), FunctionCategories.UserDefined, returnType, 0, args.Count, args.Count, argTypes)
+        {
+            this._args = args;
+            this._isImperative = isImperative;
+
+            this.UdfBody = body;
+        }
+
+        public static IEnumerable<UserDefinedFunction> CreateFunctionsWithSignatures(IEnumerable<UDF> uDFs, INameResolver nameResolver, IDictionary<UDF, string> descriptions, out List<TexlError> errors)
+        {
+            Contracts.AssertValue(uDFs);
+            Contracts.AssertAllValues(uDFs);
+
+            var userDefinedFunctions = new List<UserDefinedFunction>();
+            var texlFunctionSet = new TexlFunctionSet();
+            errors = new List<TexlError>();
+
+            foreach (var udf in uDFs)
+            {
+                Contracts.Assert(udf.IsParseValid);
+
+                var udfName = udf.Ident.Name;
+                if (texlFunctionSet.AnyWithName(udfName))
+                {
+                    errors.Add(new TexlError(udf.Ident, DocumentErrorSeverity.Severe, TexlStrings.ErrUDF_FunctionAlreadyDefined, udfName));
+                    continue;
+                }
+                else if (_restrictedUDFNames.Contains(udfName) ||
+                    nameResolver.Functions.WithName(udfName).Any(func => func.IsRestrictedUDFName))
+                {
+                    errors.Add(new TexlError(udf.Ident, DocumentErrorSeverity.Severe, TexlStrings.ErrUDF_FunctionNameRestricted, udfName));
+                    continue;
+                }
+
+                if (udf.Args.Count > MaxParameterCount)
+                {
+                    errors.Add(new TexlError(udf.Ident, DocumentErrorSeverity.Severe, TexlStrings.ErrUDF_TooManyParameters, udfName, MaxParameterCount));
+                    continue;
+                }
+
+                var parametersOk = CheckParameters(udf.Args, errors, nameResolver, out var parameterTypes);
+                var returnTypeOk = CheckReturnType(udf.ReturnType, errors, nameResolver, out var returnType);
+                if (!parametersOk || !returnTypeOk)
+                {
+                    continue;
+                }
+
+                if (nameResolver.Functions.WithName(udfName).Any())
+                {
+                    errors.Add(new TexlError(udf.Ident, DocumentErrorSeverity.Warning, TexlStrings.WrnUDF_ShadowingBuiltInFunction, udfName));
+                }
+
+                descriptions.TryGetValue(udf, out var description);
+
+                var func = new UserDefinedFunction(udfName.Value, returnType, udf.Body, udf.IsImperative, udf.Args, parameterTypes, description);
+
+                texlFunctionSet.Add(func);
+                userDefinedFunctions.Add(func);
+            }
+
+            return userDefinedFunctions;
+        }
+
         /// <summary>
         /// Gets argument index for a given argument.
         /// </summary>
@@ -208,7 +272,7 @@ public UserDefinedFunction WithBinding(INameResolver nameResolver, IBinderGlue b
                 throw new ArgumentNullException(nameof(binderGlue));
             }
 
-            var func = new UserDefinedFunction(Name, ReturnType, UdfBody, _isImperative, new HashSet<UDFArg>(_args), ParamTypes);
+            var func = new UserDefinedFunction(Name, ReturnType, UdfBody, _isImperative, new HashSet<UDFArg>(_args), ParamTypes, this.Description);
             binding = func.BindBody(nameResolver, binderGlue, bindingConfig, features, rule);
 
             return func;

From 9a94cffa189960718e75ed38dc2b9cff5ca5ecb4 Mon Sep 17 00:00:00 2001
From: "Rick Nguyen (from Dev Box)" <ricknguyen@microsoft.com>
Date: Thu, 19 Sep 2024 04:24:58 -0700
Subject: [PATCH 2/6] get comments

---
 .../Functions/UserDefinedFunction.cs          | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs b/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
index 9d5b4eb76d..789b47f260 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
@@ -5,6 +5,7 @@
 using System.Collections.Generic;
 using System.Data;
 using System.Linq;
+using System.Text;
 using Microsoft.CodeAnalysis;
 using Microsoft.PowerFx.Core.App;
 using Microsoft.PowerFx.Core.App.Controls;
@@ -157,6 +158,59 @@ public static IEnumerable<UserDefinedFunction> CreateFunctionsWithSignatures(IEn
             return userDefinedFunctions;
         }
 
+        public static Dictionary<UDF, string> CommentsByUdf(string script, ParserOptions parserOptions, out ParseUserDefinitionResult parseResult)
+        {
+            parseResult = TexlParser.ParseUserDefinitionScript(script, parserOptions);
+            var spans = new List<(int, int, Token, UDF)>();
+            var commentsByUdf = new Dictionary<UDF, string>();
+            foreach (var udf in parseResult.UDFs)
+            {
+                var span = udf.Ident.Span;
+                spans.Add((udf.Ident.Span.Min, udf.Body.GetCompleteSpan().Lim, null, udf));
+            }
+
+            foreach (var comment in parseResult.Comments ?? Enumerable.Empty<Token>())
+            {
+                spans.Add((comment.Span.Min, comment.Span.Lim, comment, null));
+            }
+
+            spans.Sort((a, b) => a.Item1.CompareTo(b.Item1));
+
+            var descripion = new StringBuilder();
+            foreach (var span in spans)
+            {
+                var (low, high, comment, udf) = span;
+                if (comment != null)
+                {
+                    var commentText = comment.Span.GetFragment(script);
+                    var isMultliLineComment = commentText.StartsWith("/*", StringComparison.InvariantCulture);
+                    if (isMultliLineComment)
+                    {
+                        commentText = commentText.Replace("/*", string.Empty).Replace("*/", string.Empty);
+                    }
+                    else
+                    {
+                        commentText = commentText.Replace("//", string.Empty);
+                    }
+
+                    commentText = commentText.Trim();   
+                    if (!commentText.EndsWith("\n", StringComparison.InvariantCulture))
+                    {
+                        commentText += "\n";
+                    }
+
+                    descripion.Append(commentText);
+                }
+                else
+                {
+                    commentsByUdf[udf] = descripion.ToString();
+                    descripion = new StringBuilder();
+                }
+            }
+
+            return commentsByUdf;
+        }
+
         /// <summary>
         /// Gets argument index for a given argument.
         /// </summary>

From 28b83897f845b6f02f6d9edef56c24ba2bd57bd3 Mon Sep 17 00:00:00 2001
From: "Rick Nguyen (from Dev Box)" <ricknguyen@microsoft.com>
Date: Thu, 19 Sep 2024 15:37:56 -0700
Subject: [PATCH 3/6] expose pretty printer

---
 .../Syntax/TexlPretty.cs                      | 52 +++++++++----------
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs b/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs
index 50991cb40f..b91689ffe9 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs
@@ -66,19 +66,19 @@ public override LazyList<string> Visit(NumLitNode node, Precedence parentPrecede
         {
             Contracts.AssertValue(node);
 
-            var nlt = node.Value;
-
-            // $$$ can't use current culture
+            var nlt = node.Value;
+
+            // $$$ can't use current culture
             return LazyList<string>.Of(nlt != null ? nlt.ToString() : node.NumValue.ToString("R", CultureInfo.CurrentCulture));
-        }
-
+        }
+
         public override LazyList<string> Visit(DecLitNode node, Precedence parentPrecedence)
         {
             Contracts.AssertValue(node);
 
-            var nlt = node.Value;
-
-            // $$$ can't use current culture
+            var nlt = node.Value;
+
+            // $$$ can't use current culture
             return LazyList<string>.Of(nlt != null ? nlt.ToString() : node.DecValue.ToString("G29", CultureInfo.CurrentCulture));
         }
 
@@ -250,7 +250,7 @@ public override LazyList<string> Visit(VariadicOpNode node, Precedence parentPre
 
             switch (node.Op)
             {
-                case VariadicOp.Chain:
+                case VariadicOp.Chain:
                     // $$$ can't use current culture
                     var op = SpacedOper(TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorChainingSeparator);
                     var count = node.Count;
@@ -261,7 +261,7 @@ public override LazyList<string> Visit(VariadicOpNode node, Precedence parentPre
                         result = result
                             .With(node.Children[i].Accept(this, Precedence.None));
                         if (i != count - 1)
-                        {
+                        {
                             // $$$ can't use current culture
                             result = result.With(SpacedOper(TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorChainingSeparator));
                         }
@@ -330,7 +330,7 @@ public override LazyList<string> Visit(CallNode node, Precedence parentPrecedenc
         public override LazyList<string> Visit(ListNode node, Precedence parentPrecedence)
         {
             Contracts.AssertValue(node);
-
+
             // $$$ can't use current culture
             var listSep = TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorListSeparator + " ";
             var result = LazyList<string>.Empty;
@@ -350,7 +350,7 @@ public override LazyList<string> Visit(ListNode node, Precedence parentPrecedenc
         public override LazyList<string> Visit(RecordNode node, Precedence parentPrecedence)
         {
             Contracts.AssertValue(node);
-
+
             // $$$ can't use current culture
             var listSep = TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorListSeparator + " ";
             var result = LazyList<string>.Empty;
@@ -382,9 +382,9 @@ public override LazyList<string> Visit(RecordNode node, Precedence parentPrecede
 
         public override LazyList<string> Visit(TableNode node, Precedence parentPrecedence)
         {
-            Contracts.AssertValue(node);
-
-            // $$$ can't use current culture
+            Contracts.AssertValue(node);
+
+            // $$$ can't use current culture
             var listSep = TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorListSeparator + " ";
             var result = LazyList<string>.Empty;
             for (var i = 0; i < node.Children.Count; ++i)
@@ -399,10 +399,10 @@ public override LazyList<string> Visit(TableNode node, Precedence parentPreceden
             result = LazyList<string>.Of(TexlLexer.PunctuatorBracketOpen, " ")
                 .With(result)
                 .With(" ", TexlLexer.PunctuatorBracketClose);
-
+
             return result;
-        }
-
+        }
+
         public override LazyList<string> Visit(TypeLiteralNode node, Precedence parentPrecedence)
         {
             Contracts.AssertValue(node);
@@ -466,8 +466,8 @@ private string SpacedOper(string op)
 
     internal sealed class PrettyPrintVisitor : TexlFunctionalVisitor<LazyList<string>, PrettyPrintVisitor.Context>
     {
-        private readonly string _script;
-
+        private readonly string _script;
+
         public const string TypeInvariantFunctionName = "Type";
 
         private static readonly Dictionary<BinaryOp, Precedence> BinaryPrecedence =
@@ -491,7 +491,7 @@ internal sealed class PrettyPrintVisitor : TexlFunctionalVisitor<LazyList<string
                 { BinaryOp.LessEqual, Precedence.Compare },
             };
 
-        private PrettyPrintVisitor(string script)
+        public PrettyPrintVisitor(string script)
         {
             _script = script;
         }
@@ -508,8 +508,8 @@ public static string Format(TexlNode node, SourceList before, SourceList after,
                 .Replace("\n\n", "\n");
 
             return new Regex(@"\n +(\n +)").Replace(preRegex, (Match match) => match.Groups[1].Value);
-        }
-
+        }
+
         public static string FormatUserDefinitions(ParseUserDefinitionResult result, string formulasScript)
         {
             Contracts.AssertValue(result);
@@ -549,7 +549,7 @@ public static string FormatUserDefinitions(ParseUserDefinitionResult result, str
                 }
             }
 
-            return string.Join($"{TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorChainingSeparator}\n", definitions) +
+            return string.Join($"{TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorChainingSeparator}\n", definitions) +
                 TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorChainingSeparator;
         }
 
@@ -629,8 +629,8 @@ public override LazyList<string> Visit(NumLitNode node, Context context)
             Contracts.AssertValue(node);
 
             return Single(node);
-        }
-
+        }
+
         public override LazyList<string> Visit(DecLitNode node, Context context)
         {
             Contracts.AssertValue(node);

From 427564b6032c4861e0924ecad0c9b0928464dd08 Mon Sep 17 00:00:00 2001
From: "Rick Nguyen (from Dev Box)" <ricknguyen@microsoft.com>
Date: Thu, 19 Sep 2024 16:17:00 -0700
Subject: [PATCH 4/6] expose pretty printer2

---
 src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs b/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs
index b91689ffe9..546ef20c3e 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Syntax/TexlPretty.cs
@@ -491,7 +491,7 @@ internal sealed class PrettyPrintVisitor : TexlFunctionalVisitor<LazyList<string
                 { BinaryOp.LessEqual, Precedence.Compare },
             };
 
-        public PrettyPrintVisitor(string script)
+        internal PrettyPrintVisitor(string script)
         {
             _script = script;
         }
@@ -553,7 +553,7 @@ public static string FormatUserDefinitions(ParseUserDefinitionResult result, str
                 TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorChainingSeparator;
         }
 
-        private LazyList<string> CommentsOf(SourceList list)
+        internal LazyList<string> CommentsOf(SourceList list)
         {
             if (list == null)
             {

From 58b6b619ee82ebd23b9f452fd9f0b4dd5b1188f0 Mon Sep 17 00:00:00 2001
From: "Rick Nguyen (from Dev Box)" <ricknguyen@microsoft.com>
Date: Fri, 20 Sep 2024 10:29:16 -0700
Subject: [PATCH 5/6] asdfadsfadf

---
 .../Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs b/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
index 789b47f260..76674a6f60 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Functions/UserDefinedFunction.cs
@@ -147,9 +147,9 @@ public static IEnumerable<UserDefinedFunction> CreateFunctionsWithSignatures(IEn
                     errors.Add(new TexlError(udf.Ident, DocumentErrorSeverity.Warning, TexlStrings.WrnUDF_ShadowingBuiltInFunction, udfName));
                 }
 
-                descriptions.TryGetValue(udf, out var description);
+                var description = descriptions.ToList().First(kv => kv.Key.Ident.Name == udf.Ident.Name);
 
-                var func = new UserDefinedFunction(udfName.Value, returnType, udf.Body, udf.IsImperative, udf.Args, parameterTypes, description);
+                var func = new UserDefinedFunction(udfName.Value, returnType, udf.Body, udf.IsImperative, udf.Args, parameterTypes, description.Value);
 
                 texlFunctionSet.Add(func);
                 userDefinedFunctions.Add(func);

From f022b5c429908cca551ffb7ed0024e982cf60114 Mon Sep 17 00:00:00 2001
From: Anderson Silva <joyle@outlook.com>
Date: Mon, 9 Sep 2024 10:57:34 -0500
Subject: [PATCH 6/6] Fixing PA locale nullable (#2632)

---
 .../Texl/Intellisense/IntellisenseSuggestion.cs               | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libraries/Microsoft.PowerFx.Core/Texl/Intellisense/IntellisenseSuggestion.cs b/src/libraries/Microsoft.PowerFx.Core/Texl/Intellisense/IntellisenseSuggestion.cs
index 920423f8b2..158b5c402d 100644
--- a/src/libraries/Microsoft.PowerFx.Core/Texl/Intellisense/IntellisenseSuggestion.cs
+++ b/src/libraries/Microsoft.PowerFx.Core/Texl/Intellisense/IntellisenseSuggestion.cs
@@ -159,7 +159,7 @@ public IntellisenseSuggestion(UIString text, SuggestionKind kind, SuggestionIcon
         }
 
         public IntellisenseSuggestion(TexlFunction function, string exactMatch, UIString displayText, CultureInfo locale = null)
-            : this(displayText, SuggestionKind.Function, SuggestionIconKind.Function, function.VerifyValue().ReturnType, exactMatch, -1, function.GetDescription(locale.Name), function.VerifyValue().Name, 0)
+            : this(displayText, SuggestionKind.Function, SuggestionIconKind.Function, function.VerifyValue().ReturnType, exactMatch, -1, function.GetDescription(locale?.Name), function.VerifyValue().Name, 0)
         {
             Contracts.AssertValue(function);
 
@@ -181,7 +181,7 @@ public IntellisenseSuggestion(TexlFunction function, string exactMatch, UIString
                 }
 
                 funcDisplayString.Append(')');
-                _overloads.Add(new IntellisenseSuggestion(new UIString(funcDisplayString.ToString()), SuggestionKind.Function, SuggestionIconKind.Function, function.VerifyValue().ReturnType, exactMatch, count, function.GetDescription(locale.Name), function.Name, 0));
+                _overloads.Add(new IntellisenseSuggestion(new UIString(funcDisplayString.ToString()), SuggestionKind.Function, SuggestionIconKind.Function, function.VerifyValue().ReturnType, exactMatch, count, function.GetDescription(locale?.Name), function.Name, 0));
             }
         }