From 9f960c82c511611202214ebdbd63fbd2f7e364bf Mon Sep 17 00:00:00 2001 From: "Rick Nguyen (from Dev Box)" 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 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 CreateFunctionsWithSignatures(IEnumerable uDFs, INameResolver nameResolver, IDictionary descriptions, out List errors) + { + Contracts.AssertValue(uDFs); + Contracts.AssertAllValues(uDFs); + + var userDefinedFunctions = new List(); + var texlFunctionSet = new TexlFunctionSet(); + errors = new List(); + + 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; + } + /// /// Gets argument index for a given argument. /// @@ -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(_args), ParamTypes); + var func = new UserDefinedFunction(Name, ReturnType, UdfBody, _isImperative, new HashSet(_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)" 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 CreateFunctionsWithSignatures(IEn return userDefinedFunctions; } + public static Dictionary 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(); + 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()) + { + 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; + } + /// /// Gets argument index for a given argument. /// From 28b83897f845b6f02f6d9edef56c24ba2bd57bd3 Mon Sep 17 00:00:00 2001 From: "Rick Nguyen (from Dev Box)" 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 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.Of(nlt != null ? nlt.ToString() : node.NumValue.ToString("R", CultureInfo.CurrentCulture)); - } - + } + public override LazyList 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.Of(nlt != null ? nlt.ToString() : node.DecValue.ToString("G29", CultureInfo.CurrentCulture)); } @@ -250,7 +250,7 @@ public override LazyList 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 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 Visit(CallNode node, Precedence parentPrecedenc public override LazyList Visit(ListNode node, Precedence parentPrecedence) { Contracts.AssertValue(node); - + // $$$ can't use current culture var listSep = TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorListSeparator + " "; var result = LazyList.Empty; @@ -350,7 +350,7 @@ public override LazyList Visit(ListNode node, Precedence parentPrecedenc public override LazyList Visit(RecordNode node, Precedence parentPrecedence) { Contracts.AssertValue(node); - + // $$$ can't use current culture var listSep = TexlLexer.GetLocalizedInstance(CultureInfo.CurrentCulture).LocalizedPunctuatorListSeparator + " "; var result = LazyList.Empty; @@ -382,9 +382,9 @@ public override LazyList Visit(RecordNode node, Precedence parentPrecede public override LazyList 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.Empty; for (var i = 0; i < node.Children.Count; ++i) @@ -399,10 +399,10 @@ public override LazyList Visit(TableNode node, Precedence parentPreceden result = LazyList.Of(TexlLexer.PunctuatorBracketOpen, " ") .With(result) .With(" ", TexlLexer.PunctuatorBracketClose); - + return result; - } - + } + public override LazyList Visit(TypeLiteralNode node, Precedence parentPrecedence) { Contracts.AssertValue(node); @@ -466,8 +466,8 @@ private string SpacedOper(string op) internal sealed class PrettyPrintVisitor : TexlFunctionalVisitor, PrettyPrintVisitor.Context> { - private readonly string _script; - + private readonly string _script; + public const string TypeInvariantFunctionName = "Type"; private static readonly Dictionary BinaryPrecedence = @@ -491,7 +491,7 @@ internal sealed class PrettyPrintVisitor : TexlFunctionalVisitor 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 Visit(NumLitNode node, Context context) Contracts.AssertValue(node); return Single(node); - } - + } + public override LazyList Visit(DecLitNode node, Context context) { Contracts.AssertValue(node); From 427564b6032c4861e0924ecad0c9b0928464dd08 Mon Sep 17 00:00:00 2001 From: "Rick Nguyen (from Dev Box)" 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 CommentsOf(SourceList list) + internal LazyList CommentsOf(SourceList list) { if (list == null) { From 58b6b619ee82ebd23b9f452fd9f0b4dd5b1188f0 Mon Sep 17 00:00:00 2001 From: "Rick Nguyen (from Dev Box)" 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 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 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)); } }