зеркало из https://github.com/microsoft/Power-Fx.git
Public API to get list of functions call (#2474)
Issue https://github.com/microsoft/Power-Fx/issues/2455.
This commit is contained in:
Родитель
5126fb4b11
Коммит
c240146620
|
@ -706,6 +706,11 @@ namespace Microsoft.PowerFx
|
|||
|
||||
return summary;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFunctionNames()
|
||||
{
|
||||
return ListFunctionVisitor.Run(ApplyParse());
|
||||
}
|
||||
}
|
||||
|
||||
// Internal interface to ensure that Result objects have a common contract
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.PowerFx.Syntax
|
||||
{
|
||||
internal class ListFunctionVisitor : IdentityTexlVisitor
|
||||
{
|
||||
// FullName --> Name
|
||||
// Use Fullname as key because it's unique.
|
||||
private readonly HashSet<string> _functionNames = new HashSet<string>();
|
||||
|
||||
public static IEnumerable<string> Run(ParseResult parse)
|
||||
{
|
||||
var visitor = new ListFunctionVisitor();
|
||||
parse.Root.Accept(visitor);
|
||||
return visitor._functionNames;
|
||||
}
|
||||
|
||||
public override bool PreVisit(CallNode node)
|
||||
{
|
||||
var hasNamespace = node.Head.Namespace.Length > 0;
|
||||
|
||||
var name = node.Head.Name;
|
||||
var fullName = hasNamespace ?
|
||||
node.Head.Namespace + "." + name :
|
||||
name;
|
||||
|
||||
_functionNames.Add(fullName);
|
||||
|
||||
return base.PreVisit(node);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.PowerFx.Core.Tests
|
||||
{
|
||||
public class ListFunctionVisitorTests : PowerFxTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Abs(1)", "Abs")]
|
||||
[InlineData("Abs(Abs(Abs(Abs(Abs(1)))))", "Abs")]
|
||||
[InlineData("With({x:Today()}, x+1)", "With,Today")]
|
||||
[InlineData("SomeNameSpace.Foo() + SomeNameSpace.Bar()", "SomeNameSpace.Foo,SomeNameSpace.Bar")]
|
||||
[InlineData("true And true", "")]
|
||||
[InlineData("If(true, Blank(),Error())", "If,Blank,Error")]
|
||||
public void ListFunctionNamesTest(string expression, string expectedNames)
|
||||
{
|
||||
foreach (var textFirst in new bool[] { false, true })
|
||||
{
|
||||
if (textFirst)
|
||||
{
|
||||
expression = $"={expression}";
|
||||
}
|
||||
|
||||
CheckFunctionNames(textFirst, expression, expectedNames);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Hello ${Sum(1,Sqrt(2))} world", "Sum,Sqrt")]
|
||||
[InlineData("3 ' {} ${Upper(3+3)} \" ${Lower($\"{7+7}\")}", "Upper,Lower")]
|
||||
public void ListFunctionNamesTextFirstTest(string expression, string expectedNames)
|
||||
{
|
||||
CheckFunctionNames(true, expression, expectedNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListFunctionNamesErrorTest()
|
||||
{
|
||||
var checkResult = new CheckResult(new Engine());
|
||||
Assert.Throws<InvalidOperationException>(() => checkResult.GetFunctionNames());
|
||||
}
|
||||
|
||||
private static void CheckFunctionNames(bool textFirst, string expression, string expectedNames)
|
||||
{
|
||||
var options = new ParserOptions() { TextFirst = textFirst };
|
||||
var engine = new Engine();
|
||||
var check = engine.Check(expression, options);
|
||||
var checkResult = new CheckResult(engine).SetText(expression, options);
|
||||
|
||||
var functionsNames1 = check.GetFunctionNames();
|
||||
var functionsNames2 = checkResult.GetFunctionNames();
|
||||
|
||||
var actualNames1 = string.Join(",", functionsNames1);
|
||||
var actualNames2 = string.Join(",", functionsNames2);
|
||||
|
||||
Assert.Equal(expectedNames, actualNames1);
|
||||
Assert.Equal(expectedNames, actualNames2);
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче