Remove Elsa.Expressions.Dsl module and related DSL features

This commit completely removes the Elsa.Expressions.Dsl module, including all associated features, services, models, and dependencies. The DSL functionality, including its custom activities and integration options, has been fully eliminated from the project.
This commit is contained in:
Sipke Schoorstra 2025-06-02 21:52:10 +02:00
parent 1f2353cad8
commit 8fb797eaeb
No known key found for this signature in database
GPG key ID: 5C10502B28A4268F
143 changed files with 2144 additions and 5488 deletions

View file

@ -240,8 +240,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Http", "src\modules\El
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Expressions.CSharp", "src\modules\Elsa.Expressions.CSharp\Elsa.Expressions.CSharp.csproj", "{16C3FBDE-A832-E3CD-5FBF-F51744D1F79B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Expressions.Dsl", "src\modules\Elsa.Expressions.Dsl\Elsa.Expressions.Dsl.csproj", "{765392DE-8560-B464-62DD-6890720FF5D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Expressions.JavaScript", "src\modules\Elsa.Expressions.JavaScript\Elsa.Expressions.JavaScript.csproj", "{099D5DCE-CCF7-16FE-6EDC-A64B694F50BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Expressions.JavaScript.Libraries", "src\modules\Elsa.Expressions.JavaScript.Libraries\Elsa.Expressions.JavaScript.Libraries.csproj", "{08B69CC4-B5F0-44E8-FA7A-6BF6F00CA40A}"
@ -262,6 +260,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Resilience", "src\modu
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.WorkflowProviders.BlobStorage", "src\modules\Elsa.WorkflowProviders.BlobStorage\Elsa.WorkflowProviders.BlobStorage.csproj", "{0125BC8D-C837-414C-BB53-FCEA62E3060F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scheduling", "scheduling", "{7C038270-8BF7-4911-AC24-54D7BBE9BBF2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Scheduling", "src\modules\Elsa.Scheduling\Elsa.Scheduling.csproj", "{26849C37-2ACA-4DDE-83CD-B87939465791}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -410,10 +412,6 @@ Global
{16C3FBDE-A832-E3CD-5FBF-F51744D1F79B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16C3FBDE-A832-E3CD-5FBF-F51744D1F79B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16C3FBDE-A832-E3CD-5FBF-F51744D1F79B}.Release|Any CPU.Build.0 = Release|Any CPU
{765392DE-8560-B464-62DD-6890720FF5D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{765392DE-8560-B464-62DD-6890720FF5D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{765392DE-8560-B464-62DD-6890720FF5D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{765392DE-8560-B464-62DD-6890720FF5D5}.Release|Any CPU.Build.0 = Release|Any CPU
{099D5DCE-CCF7-16FE-6EDC-A64B694F50BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{099D5DCE-CCF7-16FE-6EDC-A64B694F50BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{099D5DCE-CCF7-16FE-6EDC-A64B694F50BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -450,6 +448,10 @@ Global
{0125BC8D-C837-414C-BB53-FCEA62E3060F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0125BC8D-C837-414C-BB53-FCEA62E3060F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0125BC8D-C837-414C-BB53-FCEA62E3060F}.Release|Any CPU.Build.0 = Release|Any CPU
{26849C37-2ACA-4DDE-83CD-B87939465791}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26849C37-2ACA-4DDE-83CD-B87939465791}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26849C37-2ACA-4DDE-83CD-B87939465791}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26849C37-2ACA-4DDE-83CD-B87939465791}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -516,7 +518,6 @@ Global
{C55015F0-E9DF-4BF9-8131-D7539E938220} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
{E0B22AB7-7CB5-6D17-562C-4A989DC61F8A} = {C55015F0-E9DF-4BF9-8131-D7539E938220}
{16C3FBDE-A832-E3CD-5FBF-F51744D1F79B} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
{765392DE-8560-B464-62DD-6890720FF5D5} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
{099D5DCE-CCF7-16FE-6EDC-A64B694F50BE} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
{08B69CC4-B5F0-44E8-FA7A-6BF6F00CA40A} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
{6AF53651-99F0-1DE0-D37B-4FF6B0348DBB} = {6EF07978-A6D2-40EB-891D-7D70C5F37E76}
@ -527,6 +528,8 @@ Global
{58064618-A7BD-4D3E-8D57-B15018110AB5} = {E023660A-162E-498E-BA00-A941FBC82664}
{467573C9-DDC7-4351-9EC8-22E23F554DA7} = {E023660A-162E-498E-BA00-A941FBC82664}
{0125BC8D-C837-414C-BB53-FCEA62E3060F} = {B08B4E00-C2AB-48F3-8389-449F42AEF179}
{7C038270-8BF7-4911-AC24-54D7BBE9BBF2} = {5BA4A8FA-F7F4-45B3-AEC8-8886D35AAC79}
{26849C37-2ACA-4DDE-83CD-B87939465791} = {7C038270-8BF7-4911-AC24-54D7BBE9BBF2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D4B5CEAA-7D70-4FCB-A68E-B03FBE5E0E5E}

View file

@ -3,6 +3,7 @@ using Elsa.Caching.Options;
using Elsa.Common.RecurringTasks;
using Elsa.Expressions.Helpers;
using Elsa.Extensions;
using Elsa.Features.Services;
using Elsa.Identity.Multitenancy;
using Elsa.Server.Web.Filters;
using Elsa.Tenants.AspNetCore;
@ -15,14 +16,13 @@ using Elsa.Workflows.LogPersistence;
using Elsa.Workflows.Options;
using Elsa.Workflows.Runtime.Options;
using Elsa.Workflows.Runtime.Tasks;
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
// ReSharper disable RedundantAssignment
const bool useZipCompression = false;
const bool useReadOnlyMode = false;
const bool useSignalR = false; // Disabled until Elsa Studio sends authenticated requests.
const bool useMultitenancy = false;
const bool useTenantsFromConfiguration = true;
const bool disableVariableWrappers = false;
ObjectConverter.StrictMode = true;
@ -55,19 +55,14 @@ services
strategies.AddStandardStrategies();
strategies.Add("Every 10 seconds", new PeriodicWorkflowStrategy(TimeSpan.FromSeconds(10)));
});
workflows.UseCaching();
})
.UseWorkflowManagement(management =>
{
management.SetDefaultLogPersistenceMode(LogPersistenceMode.Inherit);
management.UseCaching();
management.UseCache();
management.UseReadOnlyMode(useReadOnlyMode);
})
.UseWorkflowRuntime(runtime =>
{
runtime.UseCaching();
})
.UseWorkflowRuntime(runtime => runtime.UseCache())
.UseWorkflowsApi()
.UseCSharp(options =>
{
@ -104,8 +99,7 @@ services
{
http.ConfigureHttpOptions = options => configuration.GetSection("Http").Bind(options);
http.UseCache();
})
;
});
ConfigureForTest?.Invoke(elsa);
});

View file

@ -1,26 +0,0 @@
using Elsa.Extensions;
using Elsa.Workflows;
namespace Elsa.ServerAndStudio.Web.Activities;
public class CustomDelay : Activity
{
protected override ValueTask ExecuteAsync(ActivityExecutionContext context)
{
context.DelayFor(TimeSpan.FromSeconds(5), FailAsync);
context.DelayFor(TimeSpan.FromSeconds(500), OnDelayElapsedAsync);
return default;
}
private ValueTask FailAsync(ActivityExecutionContext context)
{
Console.WriteLine("Failing!");
throw new("Failing!");
}
private async ValueTask OnDelayElapsedAsync(ActivityExecutionContext context)
{
Console.WriteLine("Delay elapsed");
await context.CompleteActivityAsync();
}
}

View file

@ -1,18 +0,0 @@
using Elsa.Expressions.Models;
using Elsa.Scheduling.Activities;
using Elsa.Workflows;
namespace Elsa.ServerAndStudio.Web.Activities;
public class CustomTimer : TimerBase
{
protected override TimeSpan GetInterval(ExpressionExecutionContext context)
{
return TimeSpan.FromSeconds(5);
}
protected override void OnTimerElapsed(ActivityExecutionContext context)
{
Console.WriteLine("Timer elapsed");
}
}

View file

@ -1,18 +1,8 @@
using Elsa.Agents;
using Elsa.Expressions.JavaScript.Libraries.Extensions;
using Elsa.Extensions;
using Elsa.Persistence.EFCore.Extensions;
using Elsa.Persistence.EFCore.Modules.Management;
using Elsa.Persistence.EFCore.Modules.Runtime;
using Elsa.ServerAndStudio.Web.Enums;
using Elsa.ServerAndStudio.Web.Extensions;
using Elsa.ServiceBus.MassTransit.Extensions;
using Elsa.ServiceBus.MassTransit.Options;
using Medallion.Threading.FileSystem;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Proto.Persistence.Sqlite;
using WebhooksCore.Options;
const bool useMassTransit = true;
const bool useProtoActor = true;
@ -24,22 +14,11 @@ var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseStaticWebAssets();
var services = builder.Services;
var configuration = builder.Configuration;
var sqliteConnectionString = configuration.GetConnectionString("Sqlite")!;
var mySqlConnectionString = configuration.GetConnectionString("MySql")!;
var sqlServerConnectionString = configuration.GetConnectionString("SqlServer")!;
var postgreSqlConnectionString = configuration.GetConnectionString("PostgreSql")!;
var rabbitMqConnectionString = configuration.GetConnectionString("RabbitMq")!;
var azureServiceBusConnectionString = configuration.GetConnectionString("AzureServiceBus")!;
var identitySection = configuration.GetSection("Identity");
var identityTokenSection = identitySection.GetSection("Tokens");
var massTransitSection = configuration.GetSection("MassTransit");
var massTransitDispatcherSection = configuration.GetSection("MassTransit.Dispatcher");
var heartbeatSection = configuration.GetSection("Heartbeat");
var sqlDatabaseProvider = Enum.Parse<SqlDatabaseProvider>(configuration["DatabaseProvider"] ?? "Sqlite");
services.Configure<MassTransitOptions>(massTransitSection);
services.Configure<MassTransitWorkflowDispatcherOptions>(massTransitDispatcherSection);
// Add Elsa services.
services
.AddElsa(elsa =>
@ -54,66 +33,15 @@ services
identity.UseConfigurationBasedRoleProvider(options => identitySection.Bind(options));
})
.UseDefaultAuthentication()
.UseApplicationCluster(x => x.HeartbeatOptions = settings => heartbeatSection.Bind(settings))
.UseWorkflowManagement(management =>
{
if (useMassTransit)
{
management.UseMassTransitDispatcher();
}
if (useCaching)
management.UseCache();
if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer)
management.UseEntityFrameworkCore(ef => ef.UseSqlServer(sqlServerConnectionString));
else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql)
management.UseEntityFrameworkCore(ef => ef.UsePostgreSql(postgreSqlConnectionString));
else if (sqlDatabaseProvider == SqlDatabaseProvider.Sqlite)
management.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString));
#if !NET9_0
else if (sqlDatabaseProvider == SqlDatabaseProvider.MySql)
management.UseEntityFrameworkCore(ef => ef.UseMySql(mySqlConnectionString));
#endif
})
.UseWorkflowManagement(management => management.UseCache())
.UseWorkflowRuntime(runtime =>
{
if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer)
runtime.UseEntityFrameworkCore(ef => ef.UseSqlServer(sqlServerConnectionString));
else if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql)
runtime.UseEntityFrameworkCore(ef => ef.UsePostgreSql(postgreSqlConnectionString));
else if (sqlDatabaseProvider == SqlDatabaseProvider.Sqlite)
runtime.UseEntityFrameworkCore(ef => ef.UseSqlite(sqliteConnectionString));
#if !NET9_0
else if (sqlDatabaseProvider == SqlDatabaseProvider.MySql)
runtime.UseEntityFrameworkCore(ef => ef.UseMySql(mySqlConnectionString));
#endif
if (useMassTransit)
{
runtime.UseMassTransitDispatcher();
}
if (useProtoActor)
{
runtime.UseProtoActor();
}
if (useCaching)
runtime.UseCache();
runtime.UseCache();
runtime.DistributedLockProvider = _ => new FileDistributedSynchronizationProvider(new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "App_Data", "locks")));
runtime.WorkflowInboxCleanupOptions = options => configuration.GetSection("Runtime:WorkflowInboxCleanup").Bind(options);
runtime.WorkflowDispatcherOptions = options => configuration.GetSection("Runtime:WorkflowDispatcher").Bind(options);
})
.UseScheduling()
.UseJavaScript(javaScriptFeature =>
{
javaScriptFeature
.ConfigureJintOptions(jintOptions => jintOptions.AllowClrAccess = true)
.UseLodashFp()
.UseMoment();
})
.UseJavaScript(javaScriptFeature => javaScriptFeature.ConfigureJintOptions(jintOptions => jintOptions.AllowClrAccess = true))
.UseLiquid()
.UseCSharp()
.UsePython(python =>
@ -136,59 +64,12 @@ services
options.BasePath = configuration["Http:BasePath"];
};
})
.UseEmail(email => email.ConfigureOptions = options => configuration.GetSection("Smtp").Bind(options))
.UseWebhooks(webhooks => webhooks.ConfigureSinks = options => builder.Configuration.GetSection("Webhooks:Sinks").Bind(options))
.UseWorkflowsApi()
.AddActivitiesFrom<Program>()
.AddWorkflowsFrom<Program>();
if (useProtoActor)
{
elsa.UseProtoActor(proto => proto.PersistenceProvider = _ =>
{
return new SqliteProvider(new SqliteConnectionStringBuilder(sqliteConnectionString));
});
}
if (useMassTransit)
{
elsa.UseMassTransit(massTransit =>
{
switch (useMassTransitBroker)
{
case MassTransitBroker.AzureServiceBus:
massTransit.UseAzureServiceBus(azureServiceBusConnectionString, asb =>
{
asb.SubscriptionCleanupOptions = options => options.Interval = TimeSpan.FromMinutes(5);
asb.EnableAutomatedSubscriptionCleanup = true;
});
break;
case MassTransitBroker.RabbitMq:
massTransit.UseRabbitMq(rabbitMqConnectionString);
break;
}
}
);
}
if (distributedCachingTransport != DistributedCachingTransport.None)
{
elsa.UseDistributedCache(distributedCaching =>
{
if (distributedCachingTransport == DistributedCachingTransport.MassTransit) distributedCaching.UseMassTransit();
});
}
elsa.UseConnections(
configure=> configure.AddConnectionsFrom<Program>());
elsa.UseConnectionPersistence(ef=> ef.UseEntityFrameworkCore(f=>f.UseSqlite()));
elsa.UseConnectionsApi();
});
services.Configure<WebhookSinksOptions>(options => configuration.GetSection("Webhooks").Bind(options));
services.AddHealthChecks();
services.AddCors(cors => cors.Configure(configuration.GetSection("CorsPolicy")));
// Razor Pages.

View file

@ -17,6 +17,7 @@
<ProjectReference Include="..\..\modules\Elsa.Expressions.CSharp\Elsa.Expressions.CSharp.csproj" />
<ProjectReference Include="..\..\modules\Elsa.Expressions.JavaScript\Elsa.Expressions.JavaScript.csproj" />
<ProjectReference Include="..\..\modules\Elsa.Expressions.Liquid\Elsa.Expressions.Liquid.csproj" />
<ProjectReference Include="..\..\modules\Elsa.WorkflowProviders.BlobStorage\Elsa.WorkflowProviders.BlobStorage.csproj" />
<ProjectReference Include="..\..\modules\Elsa\Elsa.csproj" />
<ProjectReference Include="..\Elsa.Testing.Shared\Elsa.Testing.Shared.csproj" />
</ItemGroup>

View file

@ -38,7 +38,6 @@ public class TestApplicationBuilder
.UseCSharp()
.UseJavaScript()
.UseLiquid()
.UseDsl()
.UseWorkflowManagement()
.UseWorkflows(workflows => workflows
.WithStandardOutStreamProvider(_ => new StandardOutStreamProvider(new XunitConsoleTextWriter(_testOutputHelper)))

View file

@ -1,223 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// ANTLR Version: 4.10.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// Generated from C:/Projects/Elsa/v3/src/dsl/Elsa.Expressions.Dsl/Dsl\ElsaLexer.g4 by ANTLR 4.10.1
// Unreachable code detected
#pragma warning disable 0162
// The variable '...' is assigned but its value is never used
#pragma warning disable 0219
// Missing XML comment for publicly visible type or member '...'
#pragma warning disable 1591
// Ambiguous reference in cref attribute
#pragma warning disable 419
using System;
using System.IO;
using System.Text;
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using DFA = Antlr4.Runtime.Dfa.DFA;
[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.10.1")]
[System.CLSCompliant(false)]
public partial class ElsaLexer : Lexer {
protected static DFA[] decisionToDFA;
protected static PredictionContextCache sharedContextCache = new PredictionContextCache();
public const int
EQ=1, GREATER=2, INCREMENT=3, DECREMENT=4, NEW=5, VARIABLE=6, LET=7, IF=8,
THEN=9, ELSE=10, FOR=11, RETURN=12, VOID=13, FLOAT=14, INT=15, STRING=16,
OBJECT=17, EXPRESSION_MARKER=18, SYMBOL=19, COLON=20, SEMICOLON=21, COMMA=22,
PLUS=23, MINUS=24, STAR=25, EQUALS=26, NOT_EQUALS=27, GREATER_EQUALS=28,
LESS=29, LESS_EQUALS=30, LAMBDA=31, PARENTHESES_OPEN=32, PARENTHESES_CLOSE=33,
BRACKET_OPEN=34, BRACKET_CLOSE=35, CURLYBRACE_OPEN=36, CURLYBRACE_CLOSE=37,
EXCLAMATION=38, PIPE=39, PIPE_DBL=40, PERIOD=41, STRING_VAL=42, BACKTICKSTRING_VAL=43,
LINE_COMMENT=44, INTEGER_VAL=45, ID=46, WS=47, ESC=48;
public static string[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
public static string[] modeNames = {
"DEFAULT_MODE"
};
public static readonly string[] ruleNames = {
"EQ", "GREATER", "INCREMENT", "DECREMENT", "NEW", "VARIABLE", "LET", "IF",
"THEN", "ELSE", "FOR", "RETURN", "VOID", "FLOAT", "INT", "STRING", "OBJECT",
"EXPRESSION_MARKER", "SYMBOL", "COLON", "SEMICOLON", "COMMA", "PLUS",
"MINUS", "STAR", "EQUALS", "NOT_EQUALS", "GREATER_EQUALS", "LESS", "LESS_EQUALS",
"LAMBDA", "PARENTHESES_OPEN", "PARENTHESES_CLOSE", "BRACKET_OPEN", "BRACKET_CLOSE",
"CURLYBRACE_OPEN", "CURLYBRACE_CLOSE", "EXCLAMATION", "PIPE", "PIPE_DBL",
"PERIOD", "STRING_VAL", "BACKTICKSTRING_VAL", "LINE_COMMENT", "INTEGER_VAL",
"ID", "WS", "LETTER", "DIGIT", "ESC"
};
public ElsaLexer(ICharStream input)
: this(input, Console.Out, Console.Error) { }
public ElsaLexer(ICharStream input, TextWriter output, TextWriter errorOutput)
: base(input, output, errorOutput)
{
Interpreter = new LexerATNSimulator(this, _ATN, decisionToDFA, sharedContextCache);
}
private static readonly string[] _LiteralNames = {
null, "'='", "'>'", "'++'", "'--'", "'new'", "'variable'", "'let'", "'if'",
"'then'", "'else'", "'for'", "'return'", "'void'", "'float'", "'int'",
"'string'", "'object'", "'expression'", null, "':'", "';'", "','", "'+'",
"'-'", "'*'", "'=='", "'!='", "'>='", "'<'", "'<='", "'=>'", "'('", "')'",
"'['", "']'", "'{'", "'}'", "'!'", "'|'", "'||'", "'.'", null, null, null,
null, null, null, "'\\|'"
};
private static readonly string[] _SymbolicNames = {
null, "EQ", "GREATER", "INCREMENT", "DECREMENT", "NEW", "VARIABLE", "LET",
"IF", "THEN", "ELSE", "FOR", "RETURN", "VOID", "FLOAT", "INT", "STRING",
"OBJECT", "EXPRESSION_MARKER", "SYMBOL", "COLON", "SEMICOLON", "COMMA",
"PLUS", "MINUS", "STAR", "EQUALS", "NOT_EQUALS", "GREATER_EQUALS", "LESS",
"LESS_EQUALS", "LAMBDA", "PARENTHESES_OPEN", "PARENTHESES_CLOSE", "BRACKET_OPEN",
"BRACKET_CLOSE", "CURLYBRACE_OPEN", "CURLYBRACE_CLOSE", "EXCLAMATION",
"PIPE", "PIPE_DBL", "PERIOD", "STRING_VAL", "BACKTICKSTRING_VAL", "LINE_COMMENT",
"INTEGER_VAL", "ID", "WS", "ESC"
};
public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames);
[NotNull]
public override IVocabulary Vocabulary
{
get
{
return DefaultVocabulary;
}
}
public override string GrammarFileName { get { return "ElsaLexer.g4"; } }
public override string[] RuleNames { get { return ruleNames; } }
public override string[] ChannelNames { get { return channelNames; } }
public override string[] ModeNames { get { return modeNames; } }
public override int[] SerializedAtn { get { return _serializedATN; } }
static ElsaLexer() {
decisionToDFA = new DFA[_ATN.NumberOfDecisions];
for (int i = 0; i < _ATN.NumberOfDecisions; i++) {
decisionToDFA[i] = new DFA(_ATN.GetDecisionState(i), i);
}
}
private static int[] _serializedATN = {
4,0,48,306,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,
7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,
7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,
7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,
7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,
7,42,2,43,7,43,2,44,7,44,2,45,7,45,2,46,7,46,2,47,7,47,2,48,7,48,2,49,
7,49,1,0,1,0,1,1,1,1,1,2,1,2,1,2,1,3,1,3,1,3,1,4,1,4,1,4,1,4,1,5,1,5,1,
5,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,8,1,8,1,8,1,8,
1,8,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,
11,1,11,1,12,1,12,1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,
14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,16,1,16,1,16,1,16,1,
16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,
18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,24,1,24,1,
25,1,25,1,25,1,26,1,26,1,26,1,27,1,27,1,27,1,28,1,28,1,29,1,29,1,29,1,
30,1,30,1,30,1,31,1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,36,1,
36,1,37,1,37,1,38,1,38,1,39,1,39,1,39,1,40,1,40,1,41,1,41,1,41,1,41,5,
41,249,8,41,10,41,12,41,252,9,41,1,41,1,41,1,42,1,42,1,42,1,42,5,42,260,
8,42,10,42,12,42,263,9,42,1,42,1,42,1,43,1,43,1,43,1,43,5,43,271,8,43,
10,43,12,43,274,9,43,1,43,3,43,277,8,43,1,43,1,43,1,43,1,43,1,44,4,44,
284,8,44,11,44,12,44,285,1,45,1,45,1,45,5,45,291,8,45,10,45,12,45,294,
9,45,1,46,1,46,1,46,1,46,1,47,1,47,1,48,1,48,1,49,1,49,1,49,3,250,261,
272,0,50,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,
13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,
25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,71,36,73,
37,75,38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46,93,47,95,0,97,
0,99,48,1,0,4,4,0,36,36,43,43,61,62,96,96,3,0,9,10,13,13,32,32,3,0,65,
90,95,95,97,122,1,0,48,57,312,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,
1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,
0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,
1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,
0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,
1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,
0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,
1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,
0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,99,
1,0,0,0,1,101,1,0,0,0,3,103,1,0,0,0,5,105,1,0,0,0,7,108,1,0,0,0,9,111,
1,0,0,0,11,115,1,0,0,0,13,124,1,0,0,0,15,128,1,0,0,0,17,131,1,0,0,0,19,
136,1,0,0,0,21,141,1,0,0,0,23,145,1,0,0,0,25,152,1,0,0,0,27,157,1,0,0,
0,29,163,1,0,0,0,31,167,1,0,0,0,33,174,1,0,0,0,35,181,1,0,0,0,37,192,1,
0,0,0,39,194,1,0,0,0,41,196,1,0,0,0,43,198,1,0,0,0,45,200,1,0,0,0,47,202,
1,0,0,0,49,204,1,0,0,0,51,206,1,0,0,0,53,209,1,0,0,0,55,212,1,0,0,0,57,
215,1,0,0,0,59,217,1,0,0,0,61,220,1,0,0,0,63,223,1,0,0,0,65,225,1,0,0,
0,67,227,1,0,0,0,69,229,1,0,0,0,71,231,1,0,0,0,73,233,1,0,0,0,75,235,1,
0,0,0,77,237,1,0,0,0,79,239,1,0,0,0,81,242,1,0,0,0,83,244,1,0,0,0,85,255,
1,0,0,0,87,266,1,0,0,0,89,283,1,0,0,0,91,287,1,0,0,0,93,295,1,0,0,0,95,
299,1,0,0,0,97,301,1,0,0,0,99,303,1,0,0,0,101,102,5,61,0,0,102,2,1,0,0,
0,103,104,5,62,0,0,104,4,1,0,0,0,105,106,5,43,0,0,106,107,5,43,0,0,107,
6,1,0,0,0,108,109,5,45,0,0,109,110,5,45,0,0,110,8,1,0,0,0,111,112,5,110,
0,0,112,113,5,101,0,0,113,114,5,119,0,0,114,10,1,0,0,0,115,116,5,118,0,
0,116,117,5,97,0,0,117,118,5,114,0,0,118,119,5,105,0,0,119,120,5,97,0,
0,120,121,5,98,0,0,121,122,5,108,0,0,122,123,5,101,0,0,123,12,1,0,0,0,
124,125,5,108,0,0,125,126,5,101,0,0,126,127,5,116,0,0,127,14,1,0,0,0,128,
129,5,105,0,0,129,130,5,102,0,0,130,16,1,0,0,0,131,132,5,116,0,0,132,133,
5,104,0,0,133,134,5,101,0,0,134,135,5,110,0,0,135,18,1,0,0,0,136,137,5,
101,0,0,137,138,5,108,0,0,138,139,5,115,0,0,139,140,5,101,0,0,140,20,1,
0,0,0,141,142,5,102,0,0,142,143,5,111,0,0,143,144,5,114,0,0,144,22,1,0,
0,0,145,146,5,114,0,0,146,147,5,101,0,0,147,148,5,116,0,0,148,149,5,117,
0,0,149,150,5,114,0,0,150,151,5,110,0,0,151,24,1,0,0,0,152,153,5,118,0,
0,153,154,5,111,0,0,154,155,5,105,0,0,155,156,5,100,0,0,156,26,1,0,0,0,
157,158,5,102,0,0,158,159,5,108,0,0,159,160,5,111,0,0,160,161,5,97,0,0,
161,162,5,116,0,0,162,28,1,0,0,0,163,164,5,105,0,0,164,165,5,110,0,0,165,
166,5,116,0,0,166,30,1,0,0,0,167,168,5,115,0,0,168,169,5,116,0,0,169,170,
5,114,0,0,170,171,5,105,0,0,171,172,5,110,0,0,172,173,5,103,0,0,173,32,
1,0,0,0,174,175,5,111,0,0,175,176,5,98,0,0,176,177,5,106,0,0,177,178,5,
101,0,0,178,179,5,99,0,0,179,180,5,116,0,0,180,34,1,0,0,0,181,182,5,101,
0,0,182,183,5,120,0,0,183,184,5,112,0,0,184,185,5,114,0,0,185,186,5,101,
0,0,186,187,5,115,0,0,187,188,5,115,0,0,188,189,5,105,0,0,189,190,5,111,
0,0,190,191,5,110,0,0,191,36,1,0,0,0,192,193,7,0,0,0,193,38,1,0,0,0,194,
195,5,58,0,0,195,40,1,0,0,0,196,197,5,59,0,0,197,42,1,0,0,0,198,199,5,
44,0,0,199,44,1,0,0,0,200,201,5,43,0,0,201,46,1,0,0,0,202,203,5,45,0,0,
203,48,1,0,0,0,204,205,5,42,0,0,205,50,1,0,0,0,206,207,5,61,0,0,207,208,
5,61,0,0,208,52,1,0,0,0,209,210,5,33,0,0,210,211,5,61,0,0,211,54,1,0,0,
0,212,213,5,62,0,0,213,214,5,61,0,0,214,56,1,0,0,0,215,216,5,60,0,0,216,
58,1,0,0,0,217,218,5,60,0,0,218,219,5,61,0,0,219,60,1,0,0,0,220,221,5,
61,0,0,221,222,5,62,0,0,222,62,1,0,0,0,223,224,5,40,0,0,224,64,1,0,0,0,
225,226,5,41,0,0,226,66,1,0,0,0,227,228,5,91,0,0,228,68,1,0,0,0,229,230,
5,93,0,0,230,70,1,0,0,0,231,232,5,123,0,0,232,72,1,0,0,0,233,234,5,125,
0,0,234,74,1,0,0,0,235,236,5,33,0,0,236,76,1,0,0,0,237,238,5,124,0,0,238,
78,1,0,0,0,239,240,5,124,0,0,240,241,5,124,0,0,241,80,1,0,0,0,242,243,
5,46,0,0,243,82,1,0,0,0,244,250,5,34,0,0,245,246,5,92,0,0,246,249,5,34,
0,0,247,249,9,0,0,0,248,245,1,0,0,0,248,247,1,0,0,0,249,252,1,0,0,0,250,
251,1,0,0,0,250,248,1,0,0,0,251,253,1,0,0,0,252,250,1,0,0,0,253,254,5,
34,0,0,254,84,1,0,0,0,255,261,5,96,0,0,256,257,5,92,0,0,257,260,5,34,0,
0,258,260,9,0,0,0,259,256,1,0,0,0,259,258,1,0,0,0,260,263,1,0,0,0,261,
262,1,0,0,0,261,259,1,0,0,0,262,264,1,0,0,0,263,261,1,0,0,0,264,265,5,
96,0,0,265,86,1,0,0,0,266,267,5,47,0,0,267,268,5,47,0,0,268,272,1,0,0,
0,269,271,9,0,0,0,270,269,1,0,0,0,271,274,1,0,0,0,272,273,1,0,0,0,272,
270,1,0,0,0,273,276,1,0,0,0,274,272,1,0,0,0,275,277,5,13,0,0,276,275,1,
0,0,0,276,277,1,0,0,0,277,278,1,0,0,0,278,279,5,10,0,0,279,280,1,0,0,0,
280,281,6,43,0,0,281,88,1,0,0,0,282,284,3,97,48,0,283,282,1,0,0,0,284,
285,1,0,0,0,285,283,1,0,0,0,285,286,1,0,0,0,286,90,1,0,0,0,287,292,3,95,
47,0,288,291,3,95,47,0,289,291,3,97,48,0,290,288,1,0,0,0,290,289,1,0,0,
0,291,294,1,0,0,0,292,290,1,0,0,0,292,293,1,0,0,0,293,92,1,0,0,0,294,292,
1,0,0,0,295,296,7,1,0,0,296,297,1,0,0,0,297,298,6,46,0,0,298,94,1,0,0,
0,299,300,7,2,0,0,300,96,1,0,0,0,301,302,7,3,0,0,302,98,1,0,0,0,303,304,
5,92,0,0,304,305,5,124,0,0,305,100,1,0,0,0,10,0,248,250,259,261,272,276,
285,290,292,1,6,0,0
};
public static readonly ATN _ATN =
new ATNDeserializer().Deserialize(_serializedATN);
}

File diff suppressed because one or more lines are too long

View file

@ -1,89 +0,0 @@
EQ=1
GREATER=2
INCREMENT=3
DECREMENT=4
NEW=5
VARIABLE=6
LET=7
IF=8
THEN=9
ELSE=10
FOR=11
RETURN=12
VOID=13
FLOAT=14
INT=15
STRING=16
OBJECT=17
EXPRESSION_MARKER=18
SYMBOL=19
COLON=20
SEMICOLON=21
COMMA=22
PLUS=23
MINUS=24
STAR=25
EQUALS=26
NOT_EQUALS=27
GREATER_EQUALS=28
LESS=29
LESS_EQUALS=30
LAMBDA=31
PARENTHESES_OPEN=32
PARENTHESES_CLOSE=33
BRACKET_OPEN=34
BRACKET_CLOSE=35
CURLYBRACE_OPEN=36
CURLYBRACE_CLOSE=37
EXCLAMATION=38
PIPE=39
PIPE_DBL=40
PERIOD=41
STRING_VAL=42
BACKTICKSTRING_VAL=43
LINE_COMMENT=44
INTEGER_VAL=45
ID=46
WS=47
ESC=48
'='=1
'>'=2
'++'=3
'--'=4
'new'=5
'variable'=6
'let'=7
'if'=8
'then'=9
'else'=10
'for'=11
'return'=12
'void'=13
'float'=14
'int'=15
'string'=16
'object'=17
'expression'=18
':'=20
';'=21
','=22
'+'=23
'-'=24
'*'=25
'=='=26
'!='=27
'>='=28
'<'=29
'<='=30
'=>'=31
'('=32
')'=33
'['=34
']'=35
'{'=36
'}'=37
'!'=38
'|'=39
'||'=40
'.'=41
'\\|'=48

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,89 +0,0 @@
EQ=1
GREATER=2
INCREMENT=3
DECREMENT=4
NEW=5
VARIABLE=6
LET=7
IF=8
THEN=9
ELSE=10
FOR=11
RETURN=12
VOID=13
FLOAT=14
INT=15
STRING=16
OBJECT=17
EXPRESSION_MARKER=18
SYMBOL=19
COLON=20
SEMICOLON=21
COMMA=22
PLUS=23
MINUS=24
STAR=25
EQUALS=26
NOT_EQUALS=27
GREATER_EQUALS=28
LESS=29
LESS_EQUALS=30
LAMBDA=31
PARENTHESES_OPEN=32
PARENTHESES_CLOSE=33
BRACKET_OPEN=34
BRACKET_CLOSE=35
CURLYBRACE_OPEN=36
CURLYBRACE_CLOSE=37
EXCLAMATION=38
PIPE=39
PIPE_DBL=40
PERIOD=41
STRING_VAL=42
BACKTICKSTRING_VAL=43
LINE_COMMENT=44
INTEGER_VAL=45
ID=46
WS=47
ESC=48
'='=1
'>'=2
'++'=3
'--'=4
'new'=5
'variable'=6
'let'=7
'if'=8
'then'=9
'else'=10
'for'=11
'return'=12
'void'=13
'float'=14
'int'=15
'string'=16
'object'=17
'expression'=18
':'=20
';'=21
','=22
'+'=23
'-'=24
'*'=25
'=='=26
'!='=27
'>='=28
'<'=29
'<='=30
'=>'=31
'('=32
')'=33
'['=34
']'=35
'{'=36
'}'=37
'!'=38
'|'=39
'||'=40
'.'=41
'\\|'=48

View file

@ -1,535 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// ANTLR Version: 4.10.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// Generated from C:/Projects/Elsa/v3/src/dsl/Elsa.Expressions.Dsl/Dsl\ElsaParser.g4 by ANTLR 4.10.1
// Unreachable code detected
#pragma warning disable 0162
// The variable '...' is assigned but its value is never used
#pragma warning disable 0219
// Missing XML comment for publicly visible type or member '...'
#pragma warning disable 1591
// Ambiguous reference in cref attribute
#pragma warning disable 419
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Tree;
using IToken = Antlr4.Runtime.IToken;
using ParserRuleContext = Antlr4.Runtime.ParserRuleContext;
/// <summary>
/// This class provides an empty implementation of <see cref="IElsaParserVisitor{Result}"/>,
/// which can be extended to create a visitor which only needs to handle a subset
/// of the available methods.
/// </summary>
/// <typeparam name="Result">The return type of the visit operation.</typeparam>
[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.10.1")]
[System.Diagnostics.DebuggerNonUserCode]
[System.CLSCompliant(false)]
public partial class ElsaParserBaseVisitor<Result> : AbstractParseTreeVisitor<Result>, IElsaParserVisitor<Result> {
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.program"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitProgram([NotNull] ElsaParser.ProgramContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.object"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitObject([NotNull] ElsaParser.ObjectContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.newObject"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitNewObject([NotNull] ElsaParser.NewObjectContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.varDecl"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitVarDecl([NotNull] ElsaParser.VarDeclContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.localVarDecl"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitLocalVarDecl([NotNull] ElsaParser.LocalVarDeclContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.type"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitType([NotNull] ElsaParser.TypeContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.expressionMarker"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitExpressionMarker([NotNull] ElsaParser.ExpressionMarkerContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.expressionContent"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitExpressionContent([NotNull] ElsaParser.ExpressionContentContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.methodCall"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitMethodCall([NotNull] ElsaParser.MethodCallContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.funcCall"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitFuncCall([NotNull] ElsaParser.FuncCallContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.args"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitArgs([NotNull] ElsaParser.ArgsContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.arg"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitArg([NotNull] ElsaParser.ArgContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.block"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitBlock([NotNull] ElsaParser.BlockContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.objectInitializer"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitObjectInitializer([NotNull] ElsaParser.ObjectInitializerContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.propertyList"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitPropertyList([NotNull] ElsaParser.PropertyListContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.property"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitProperty([NotNull] ElsaParser.PropertyContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>objectStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitObjectStat([NotNull] ElsaParser.ObjectStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>ifStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitIfStat([NotNull] ElsaParser.IfStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>forStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitForStat([NotNull] ElsaParser.ForStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>returnStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitReturnStat([NotNull] ElsaParser.ReturnStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>blockStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitBlockStat([NotNull] ElsaParser.BlockStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>variableDeclarationStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitVariableDeclarationStat([NotNull] ElsaParser.VariableDeclarationStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>localVariableDeclarationStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitLocalVariableDeclarationStat([NotNull] ElsaParser.LocalVariableDeclarationStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>assignmentStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitAssignmentStat([NotNull] ElsaParser.AssignmentStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>expressionStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitExpressionStat([NotNull] ElsaParser.ExpressionStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.thenStat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitThenStat([NotNull] ElsaParser.ThenStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.elseStat"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitElseStat([NotNull] ElsaParser.ElseStatContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>newObjectExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitNewObjectExpr([NotNull] ElsaParser.NewObjectExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>subtractExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitSubtractExpr([NotNull] ElsaParser.SubtractExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>incrementExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitIncrementExpr([NotNull] ElsaParser.IncrementExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>objectExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitObjectExpr([NotNull] ElsaParser.ObjectExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>stringValueExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitStringValueExpr([NotNull] ElsaParser.StringValueExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>multiplyExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitMultiplyExpr([NotNull] ElsaParser.MultiplyExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>parenthesesExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitParenthesesExpr([NotNull] ElsaParser.ParenthesesExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>functionExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitFunctionExpr([NotNull] ElsaParser.FunctionExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>decrementExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitDecrementExpr([NotNull] ElsaParser.DecrementExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>negateExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitNegateExpr([NotNull] ElsaParser.NegateExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>methodCallExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitMethodCallExpr([NotNull] ElsaParser.MethodCallExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>variableExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitVariableExpr([NotNull] ElsaParser.VariableExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>notExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitNotExpr([NotNull] ElsaParser.NotExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>integerValueExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitIntegerValueExpr([NotNull] ElsaParser.IntegerValueExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>addExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitAddExpr([NotNull] ElsaParser.AddExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>expressionMarkerExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitExpressionMarkerExpr([NotNull] ElsaParser.ExpressionMarkerExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>backTickStringValueExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitBackTickStringValueExpr([NotNull] ElsaParser.BackTickStringValueExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>bracketsExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitBracketsExpr([NotNull] ElsaParser.BracketsExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by the <c>compareExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitCompareExpr([NotNull] ElsaParser.CompareExprContext context) { return VisitChildren(context); }
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.exprList"/>.
/// <para>
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
/// on <paramref name="context"/>.
/// </para>
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
public virtual Result VisitExprList([NotNull] ElsaParser.ExprListContext context) { return VisitChildren(context); }
}

View file

@ -1,344 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// ANTLR Version: 4.10.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// Generated from C:/Projects/Elsa/v3/src/dsl/Elsa.Expressions.Dsl/Dsl\ElsaParser.g4 by ANTLR 4.10.1
// Unreachable code detected
#pragma warning disable 0162
// The variable '...' is assigned but its value is never used
#pragma warning disable 0219
// Missing XML comment for publicly visible type or member '...'
#pragma warning disable 1591
// Ambiguous reference in cref attribute
#pragma warning disable 419
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Tree;
using IToken = Antlr4.Runtime.IToken;
/// <summary>
/// This interface defines a complete generic visitor for a parse tree produced
/// by <see cref="ElsaParser"/>.
/// </summary>
/// <typeparam name="Result">The return type of the visit operation.</typeparam>
[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.10.1")]
[System.CLSCompliant(false)]
public interface IElsaParserVisitor<Result> : IParseTreeVisitor<Result> {
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.program"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitProgram([NotNull] ElsaParser.ProgramContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.object"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitObject([NotNull] ElsaParser.ObjectContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.newObject"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitNewObject([NotNull] ElsaParser.NewObjectContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.varDecl"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitVarDecl([NotNull] ElsaParser.VarDeclContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.localVarDecl"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitLocalVarDecl([NotNull] ElsaParser.LocalVarDeclContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.type"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitType([NotNull] ElsaParser.TypeContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.expressionMarker"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitExpressionMarker([NotNull] ElsaParser.ExpressionMarkerContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.expressionContent"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitExpressionContent([NotNull] ElsaParser.ExpressionContentContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.methodCall"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitMethodCall([NotNull] ElsaParser.MethodCallContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.funcCall"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitFuncCall([NotNull] ElsaParser.FuncCallContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.args"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitArgs([NotNull] ElsaParser.ArgsContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.arg"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitArg([NotNull] ElsaParser.ArgContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.block"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitBlock([NotNull] ElsaParser.BlockContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.objectInitializer"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitObjectInitializer([NotNull] ElsaParser.ObjectInitializerContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.propertyList"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitPropertyList([NotNull] ElsaParser.PropertyListContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.property"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitProperty([NotNull] ElsaParser.PropertyContext context);
/// <summary>
/// Visit a parse tree produced by the <c>objectStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitObjectStat([NotNull] ElsaParser.ObjectStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>ifStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitIfStat([NotNull] ElsaParser.IfStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>forStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitForStat([NotNull] ElsaParser.ForStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>returnStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitReturnStat([NotNull] ElsaParser.ReturnStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>blockStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitBlockStat([NotNull] ElsaParser.BlockStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>variableDeclarationStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitVariableDeclarationStat([NotNull] ElsaParser.VariableDeclarationStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>localVariableDeclarationStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitLocalVariableDeclarationStat([NotNull] ElsaParser.LocalVariableDeclarationStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>assignmentStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitAssignmentStat([NotNull] ElsaParser.AssignmentStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>expressionStat</c>
/// labeled alternative in <see cref="ElsaParser.stat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitExpressionStat([NotNull] ElsaParser.ExpressionStatContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.thenStat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitThenStat([NotNull] ElsaParser.ThenStatContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.elseStat"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitElseStat([NotNull] ElsaParser.ElseStatContext context);
/// <summary>
/// Visit a parse tree produced by the <c>newObjectExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitNewObjectExpr([NotNull] ElsaParser.NewObjectExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>subtractExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitSubtractExpr([NotNull] ElsaParser.SubtractExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>incrementExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitIncrementExpr([NotNull] ElsaParser.IncrementExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>objectExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitObjectExpr([NotNull] ElsaParser.ObjectExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>stringValueExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitStringValueExpr([NotNull] ElsaParser.StringValueExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>multiplyExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitMultiplyExpr([NotNull] ElsaParser.MultiplyExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>parenthesesExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitParenthesesExpr([NotNull] ElsaParser.ParenthesesExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>functionExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitFunctionExpr([NotNull] ElsaParser.FunctionExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>decrementExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitDecrementExpr([NotNull] ElsaParser.DecrementExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>negateExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitNegateExpr([NotNull] ElsaParser.NegateExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>methodCallExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitMethodCallExpr([NotNull] ElsaParser.MethodCallExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>variableExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitVariableExpr([NotNull] ElsaParser.VariableExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>notExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitNotExpr([NotNull] ElsaParser.NotExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>integerValueExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitIntegerValueExpr([NotNull] ElsaParser.IntegerValueExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>addExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitAddExpr([NotNull] ElsaParser.AddExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>expressionMarkerExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitExpressionMarkerExpr([NotNull] ElsaParser.ExpressionMarkerExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>backTickStringValueExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitBackTickStringValueExpr([NotNull] ElsaParser.BackTickStringValueExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>bracketsExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitBracketsExpr([NotNull] ElsaParser.BracketsExprContext context);
/// <summary>
/// Visit a parse tree produced by the <c>compareExpr</c>
/// labeled alternative in <see cref="ElsaParser.expr"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitCompareExpr([NotNull] ElsaParser.CompareExprContext context);
/// <summary>
/// Visit a parse tree produced by <see cref="ElsaParser.exprList"/>.
/// </summary>
/// <param name="context">The parse tree.</param>
/// <return>The visitor result.</return>
Result VisitExprList([NotNull] ElsaParser.ExprListContext context);
}

View file

@ -1 +0,0 @@
[assembly: CLSCompliant(false)]

View file

@ -1,14 +0,0 @@
using Elsa.Workflows.Activities;
namespace Elsa.Expressions.Dsl.Contracts;
/// <summary>
/// Represents a DSL engine that parse a workflow definition script into a <see cref="Workflow"/> instance.
/// </summary>
public interface IDslEngine
{
/// <summary>
/// Parses the specified script into a <see cref="Workflow"/> instance.
/// </summary>
Task<Workflow> ParseAsync(string script, CancellationToken cancellationToken = default);
}

View file

@ -1,33 +0,0 @@
using Elsa.Expressions.Dsl.Models;
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Contracts;
/// <summary>
/// Provides a registry for mapping functions to activities that can be invoked from a DSL script.
/// </summary>
public interface IFunctionActivityRegistry
{
/// <summary>
/// Registers a function that is mapped to an activity that can be invoked from a DSL script.
/// </summary>
/// <param name="functionName">The name of the function.</param>
/// <param name="activityTypeName">The name of the activity type.</param>
/// <param name="propertyNames">The names of the properties that are mapped to the function arguments.</param>
/// <param name="configure">An optional action that can be used to configure the activity.</param>
void RegisterFunction(string functionName, string activityTypeName, IEnumerable<string>? propertyNames = default, Action<IActivity>? configure = default);
/// <summary>
/// Registers a function that is mapped to an activity that can be invoked from a DSL script.
/// </summary>
/// <param name="descriptor">The descriptor that describes the function.</param>
void RegisterFunction(FunctionActivityDescriptor descriptor);
/// <summary>
/// Resolves a function to an activity that can be invoked from a DSL script.
/// </summary>
/// <param name="functionName">The name of the function.</param>
/// <param name="arguments">The arguments that are passed to the function.</param>
/// <returns>An activity that can be invoked from a DSL script.</returns>
Task<IActivity> ResolveFunctionAsync(string functionName, IEnumerable<object?>? arguments = default);
}

View file

@ -1,9 +0,0 @@
using Elsa.Workflows.Models;
namespace Elsa.Expressions.Dsl.Contracts;
public interface ITypeSystem
{
void Register(TypeDescriptor descriptor);
TypeDescriptor? ResolveTypeName(string typeName);
}

View file

@ -1,54 +0,0 @@
lexer grammar ElsaLexer;
EQ : '=';
GREATER : '>';
INCREMENT : '++';
DECREMENT : '--';
NEW : 'new';
VARIABLE : 'variable';
LET : 'let';
IF : 'if';
THEN : 'then';
ELSE : 'else';
FOR : 'for';
RETURN : 'return';
VOID : 'void';
FLOAT : 'float';
INT : 'int';
STRING : 'string';
OBJECT : 'object';
EXPRESSION_MARKER : 'expression';
SYMBOL : [=>$+`];
COLON : ':';
SEMICOLON : ';';
COMMA : ',';
PLUS : '+';
MINUS : '-';
STAR : '*';
EQUALS : '==';
NOT_EQUALS : '!=';
GREATER_EQUALS : '>=';
LESS : '<';
LESS_EQUALS : '<=';
LAMBDA : '=>';
PARENTHESES_OPEN : '(';
PARENTHESES_CLOSE : ')';
BRACKET_OPEN : '[';
BRACKET_CLOSE : ']';
CURLYBRACE_OPEN : '{';
CURLYBRACE_CLOSE : '}';
EXCLAMATION : '!';
PIPE : '|';
PIPE_DBL : '||';
PERIOD : '.';
STRING_VAL : '"' ('\\"' | .)*? '"';
BACKTICKSTRING_VAL : '`' ('\\"' | .)*? '`';
LINE_COMMENT : '//' .*? '\r'? '\n' -> skip;
INTEGER_VAL : DIGIT+;
ID : LETTER (LETTER | DIGIT)*;
WS : [ \t\r\n] -> skip;
fragment LETTER : [a-zA-Z_];
fragment DIGIT : [0-9];
ESC : '\\|';

View file

@ -1,121 +0,0 @@
parser grammar ElsaParser;
options { tokenVocab = ElsaLexer; }
program
: (stat | LINE_COMMENT)*
;
object
: ID objectInitializer?
;
newObject
: NEW ID ('<' type '>')? '(' args? ')'
;
varDecl
: VARIABLE ID (':' type)? (EQ expr)?
;
localVarDecl
: 'let' ID (':' type)? (EQ expr)?
;
type
: VOID
| FLOAT
| INT
| OBJECT
| STRING
| ID
;
expressionMarker
: EXPRESSION_MARKER '(' ID ',' expressionContent ')'
| ID '=>' expressionContent
;
expressionContent
: .*?
;
methodCall
: ID '.' funcCall
;
funcCall
: ID '(' args? ')'
;
args
: arg (',' arg)*
;
arg
: expr
| expressionMarker
;
block
: '{' stat* '}'
;
objectInitializer
: '{' propertyList? '}'
;
propertyList
: property (',' property)*
;
property
: ID ':' expr
;
stat
: object ';' #objectStat
| 'if' expr 'then' thenStat ('else' elseStat)? #ifStat
| 'for' '(' ID '=' expr ';' expr ';' expr ')' stat #forStat
| 'return' expr? ';' #returnStat
| block #blockStat
| varDecl ';' #variableDeclarationStat
| localVarDecl ';' #localVariableDeclarationStat
| expr '=' expr ';' #assignmentStat
| expr ';' #expressionStat
;
thenStat
: stat
;
elseStat
: stat
;
expr
: funcCall #functionExpr
| expressionMarker #expressionMarkerExpr
| object #objectExpr
| newObject #newObjectExpr
| expr '++' #incrementExpr
| expr '--' #decrementExpr
| '-' expr #negateExpr
| '!' expr #notExpr
| expr '*' expr #multiplyExpr
| expr '+' expr #addExpr
| expr '-' expr #subtractExpr
| expr ('==' | '>' | '<' | '!=' | '>=' | '<=') expr #compareExpr
| INTEGER_VAL #integerValueExpr
| STRING_VAL #stringValueExpr
| BACKTICKSTRING_VAL #backTickStringValueExpr
| '(' exprList? ')' #parenthesesExpr
| '[' exprList? ']' #bracketsExpr
| methodCall #methodCallExpr
| ID #variableExpr
;
exprList
: expr (',' expr)*
;

View file

@ -1,9 +0,0 @@
variable start: int = 1;
variable end: int = read();
print(js => `Counting numbers from ${start} to ${end}:`);
for(i = start; i < end; i++)
{
print(js => `Current value: ${i}`);
}

View file

@ -1,40 +0,0 @@
// Triggers when HTTP request comes in.
trigger HttpTrigger
{
Path: "/hello-world",
SupportedMethods: ["GET", "POST"]
};
// Triggers every 1 minute.
trigger TimerTrigger
{
Interval: "0:00:01:00"
};
{
// If
print("What's your age?");
variable age = ReadLine;
if age > 16 then
{
print("Enjoy your driver's license!");
delay(5000);
print("But be careful!");
}
else
print("Enjoy your bicycle!");
print("Goodbye.");
// For
variable start: int = 1;
variable end: int = 3;
print(context => $"Counting numbers from {start.Get(context)} to {end.Get(context)}");
for(i = start; i < end; i++)
{
print(context => "Current value: ${i}");
}
}

View file

@ -1,7 +0,0 @@
{
let name: string;
print("Hi! What's your name?");
read(name);
print("Nice to meet you, {name.Get(context)}!");
}

View file

@ -1,4 +0,0 @@
{
WriteLine "Hello World"
WriteLine "Goodbye cruel World"
}

View file

@ -1 +0,0 @@
WriteLine "Hello World";

View file

@ -1,14 +0,0 @@
// Triggers when HTTP request comes in.
trigger HttpTrigger
{
Path: "/hello-world",
SupportedMethods: ["GET", "POST"]
};
// Triggers every 1 minute.
trigger TimerTrigger
{
Interval: "0:00:01:00"
};
WriteLine("Hello World!");

View file

@ -1,14 +0,0 @@
print("What's your age?");
variable age = ReadLine;
if age > 16 then
{
print("Enjoy your driver's license!");
// delay(5000);
// await signal
print("But be careful!");
}
else
print("Enjoy your bicycle!");
print("Goodbye.");

View file

@ -1,10 +0,0 @@
Sequence {
Activities: [
WriteLine { Text:"writeLine1" },
Sequence {
Activities: [
WriteLine { Text:"writeLine2" }
]
}
]
};

View file

@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>
Provides a custom DSL to write workflows with in a syntax similar to JavaScript but with native keywords translating to workflow functionality.
For example if/else would translate to the If activity. Very cool, but also very experimental ;)
</Description>
<PackageTags>elsa module scripting dsl antlr4</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Antlr4.Runtime.Standard" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Elsa.Workflows.Core\Elsa.Workflows.Core.csproj" />
</ItemGroup>
</Project>

View file

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interpreters_005Cworkflowdefinitionbuilderinterpreter/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -1,14 +0,0 @@
using Elsa.Expressions.Dsl.Features;
using Elsa.Features.Services;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
public static class ModuleExtensions
{
public static IModule UseDsl(this IModule configuration, Action<DslFeature>? configure = default)
{
configuration.Configure(configure);
return configuration;
}
}

View file

@ -1,18 +0,0 @@
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
public static class ListConverter
{
public static T ConvertTo<T>(this IEnumerable<object?> items) where T : IEnumerable<object?> => (T)ConvertTo(items, typeof(T));
public static object ConvertTo(this IEnumerable<object?> items, Type type)
{
var containedType = type.GenericTypeArguments.First();
var enumerableType = typeof(Enumerable);
var castMethod = enumerableType.GetMethod(nameof(Enumerable.Cast))!.MakeGenericMethod(containedType);
var toListMethod = enumerableType.GetMethod(nameof(Enumerable.ToList))!.MakeGenericMethod(containedType);
var castedItems = castMethod.Invoke(null, new object?[] { items });
return toListMethod.Invoke(null!, new[] { castedItems })!;
}
}

View file

@ -1,42 +0,0 @@
using Elsa.Expressions.Dsl.Contracts;
using Elsa.Workflows;
using Elsa.Workflows.Models;
namespace Elsa.Expressions.Dsl.Extensions;
public static class TypeSystemExtensions
{
public static TypeDescriptor Register<T>(this ITypeSystem typeSystem, string? typeName = default) => typeSystem.Register(typeName ?? typeof(T).Name, typeof(T));
public static TypeDescriptor Register(this ITypeSystem typeSystem, string typeName, Type type)
{
var kind = GetKind(type);
var descriptor = new TypeDescriptor(typeName, type, kind);
typeSystem.Register(descriptor);
return descriptor;
}
private static TypeKind GetKind(Type type)
{
var kind = TypeKind.Unknown;
var isActivity = typeof(IActivity).IsAssignableFrom(type);
var isTrigger = typeof(IEventGenerator).IsAssignableFrom(type);
var isPrimitive = type.IsPrimitive;
var isObject = type.IsClass || type.IsValueType;
if (isActivity || isTrigger)
{
if (isActivity)
kind |= TypeKind.Activity;
if (isTrigger)
kind |= TypeKind.Trigger;
}
else if (isPrimitive)
kind = TypeKind.Primitive;
else if(isObject)
kind = TypeKind.Object;
return kind;
}
}

View file

@ -1,23 +0,0 @@
using Elsa.Expressions.Dsl.Contracts;
using Elsa.Expressions.Dsl.Services;
using Elsa.Expressions.Features;
using Elsa.Features.Abstractions;
using Elsa.Features.Attributes;
using Elsa.Features.Services;
using Microsoft.Extensions.DependencyInjection;
namespace Elsa.Expressions.Dsl.Features;
/// <inheritdoc />
[DependsOn(typeof(ExpressionsFeature))]
public class DslFeature(IModule module) : FeatureBase(module)
{
/// <inheritdoc />
public override void Configure()
{
Services
.AddScoped<IDslEngine, DslEngine>()
.AddScoped<ITypeSystem, TypeSystem>()
.AddScoped<IFunctionActivityRegistry, FunctionActivityRegistry>();
}
}

View file

@ -1,23 +0,0 @@
using Antlr4.Runtime.Tree;
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitArgs(ElsaParser.ArgsContext context)
{
var args = context.arg();
var argValues = args.Select(x =>
{
Visit(x);
var childContext = x.expr() ?? (IParseTree)x.expressionMarker();
return _expressionValue.Get(childContext);
}).ToList();
_argValues.Put(context, argValues);
return DefaultResult;
}
}

View file

@ -1,39 +0,0 @@
using Elsa.Workflows;
using Elsa.Workflows.Activities;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitBlockStat(ElsaParser.BlockStatContext context)
{
VisitChildren(context);
var value = _expressionValue.Get(context.block());
_expressionValue.Put(context, value);
return DefaultResult;
}
public override IWorkflowBuilder VisitBlock(ElsaParser.BlockContext context)
{
var sequence = new Sequence();
_containerStack.Push(sequence);
var statements = context.stat();
var values = statements.Select(x =>
{
Visit(x);
return _expressionValue.Get(x);
}).ToList();
var activities = values.OfType<IActivity>().ToList();
sequence.Activities = activities;
_containerStack.Pop();
_expressionValue.Put(context, sequence);
return DefaultResult;
}
}

View file

@ -1,28 +0,0 @@
using Elsa.Expressions.Helpers;
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
/// <inheritdoc />
public override IWorkflowBuilder VisitBracketsExpr(ElsaParser.BracketsExprContext context)
{
var propertyType = _expressionType.Get(context.Parent);
var targetElementType = propertyType?.GetGenericArguments().First() ?? typeof(object);
var contents = context.exprList().expr();
var items = contents.Select(x =>
{
Visit(x);
var stringContext = x.GetChild<ElsaParser.StringValueExprContext>(0) ?? x;
return _expressionValue.Get(stringContext);
}).ToList();
var stronglyTypedListType = targetElementType;
var stronglyTypedList = items.ConvertTo(stronglyTypedListType);
_expressionValue.Put(context, stronglyTypedList);
return DefaultResult;
}
}

View file

@ -1,24 +0,0 @@
using Elsa.Expressions.Models;
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitExpressionMarker(ElsaParser.ExpressionMarkerContext context)
{
// var language = context.ID();
// var expressionContent = context.expressionContent().GetText();
//
// // TODO: Determine actual expression type based on specified language.
// var expression = new JavaScriptExpression(expressionContent);
// var expressionReference = new JavaScriptExpressionBlockReference(expression);
// var externalReference = new ExternalExpressionReference(expression, expressionReference);
// _expressionValue.Put(context, externalReference);
// _expressionValue.Put(context.Parent, externalReference);
return DefaultResult;
}
}
public record ExternalExpressionReference(Expression Expression, MemoryBlockReference BlockReference);

View file

@ -1,38 +0,0 @@
using Elsa.Workflows;
using Elsa.Workflows.Activities;
namespace Elsa.Expressions.Dsl.Interpreters;
/// <inheritdoc />
public partial class WorkflowDefinitionBuilderInterpreter
{
/// <inheritdoc />
public override IWorkflowBuilder VisitProgram(ElsaParser.ProgramContext context)
{
var stats = context.stat();
var rootSequence = new Sequence();
// Push a sequence to allow multiple activities declared in sequence.
_containerStack.Push(rootSequence);
// Interpret child nodes.
VisitChildren(context);
// Extract activities from child nodes.
var activities = stats.Select(x => _expressionValue.Get(x) as IActivity).Where(x => x != null).Select(x => x!).ToList();
if (activities.Count == 1)
{
// We only have one activity, so we can use it as the root and discard the root sequence.
_workflowBuilder.Root = activities.Single();
}
else
{
// Assign the collected child activities to the root sequence.
rootSequence.Activities = activities.ToList();
_workflowBuilder.Root = rootSequence;
}
return DefaultResult;
}
}

View file

@ -1,35 +0,0 @@
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitExpressionStat(ElsaParser.ExpressionStatContext context)
{
VisitChildren(context);
var expressionValue = _expressionValue.Get(context.expr());
_expressionValue.Put(context, expressionValue);
return DefaultResult;
}
public override IWorkflowBuilder VisitFunctionExpr(ElsaParser.FunctionExprContext context)
{
VisitChildren(context);
var expressionValue = _expressionValue.Get(context.funcCall());
_expressionValue.Put(context, expressionValue);
return DefaultResult;
}
public override IWorkflowBuilder VisitFuncCall(ElsaParser.FuncCallContext context)
{
VisitChildren(context);
var functionName = context.ID().GetText();
var argsNode = context.args();
var args = argsNode != null ? _argValues.Get(context.args()) : default;
var activity = _functionActivityRegistry.ResolveFunctionAsync(functionName, args).GetAwaiter().GetResult();
_expressionValue.Put(context, activity);
return DefaultResult;
}
}

View file

@ -1,33 +0,0 @@
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitIfStat(ElsaParser.IfStatContext context)
{
// var ifActivity = new If();
// var conditionExpr = context.expr().GetText();
//
// var javaScriptExpression = new JavaScriptExpression(conditionExpr);
// ifActivity.Condition = new Input<bool>(javaScriptExpression, new JavaScriptExpressionBlockReference(javaScriptExpression));
//
// var thenStat = context.thenStat().stat();
// var elseStat = context.elseStat()?.stat();
//
// Visit(thenStat);
//
// var thenActivity = _expressionValue.Get(thenStat);
// ifActivity.Then = (IActivity?)thenActivity;
//
// if (elseStat != null)
// {
// Visit(elseStat);
// var elseActivity = _expressionValue.Get(elseStat);
// ifActivity.Else = (IActivity?)elseActivity;
// }
//
// _expressionValue.Put(context, ifActivity);
return DefaultResult;
}
}

View file

@ -1,27 +0,0 @@
using Elsa.Expressions.Dsl.Models;
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitLocalVarDecl(ElsaParser.LocalVarDeclContext context)
{
var variableName = context.ID().GetText();
var variableType = context.type()?.ID().GetText();
VisitChildren(context);
var value = _expressionValue.Get(context.expr());
var variable = new DefinedVariable
{
Identifier = variableName,
Value = value
};
_definedVariables[variableName] = variable;
return DefaultResult;
}
}

View file

@ -1,52 +0,0 @@
using Elsa.Workflows;
using Elsa.Workflows.Models;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitNewObjectExpr(ElsaParser.NewObjectExprContext context)
{
VisitChildren(context);
var value = _expressionValue.Get(context.newObject());
_expressionValue.Put(context, value);
return DefaultResult;
}
public override IWorkflowBuilder VisitNewObject(ElsaParser.NewObjectContext context)
{
var objectTypeName = context.ID().GetText();
var typeArg = context.type()?.GetText();
TypeDescriptor? typeArgTypeDescriptor = default;
if (typeArg != null)
{
objectTypeName = $"{objectTypeName}<>";
typeArgTypeDescriptor = _typeSystem.ResolveTypeName(typeArg) ?? throw new Exception($"Cannot use type {typeArg} as type argument because it was not found in the type system.");
}
var typeDescriptor = _typeSystem.ResolveTypeName(objectTypeName);
if (typeDescriptor == null)
throw new Exception($"Could not instantiate type {objectTypeName} because it was not found in the type system.");
VisitChildren(context);
var argValues = _argValues.Get(context.args()).ToArray();
var objectType = typeDescriptor.Type;
if (typeArgTypeDescriptor != null)
{
var objectTypeArg = typeArgTypeDescriptor.Type;
objectType = objectType.MakeGenericType(objectTypeArg);
}
var objectInstance = Activator.CreateInstance(objectType, argValues);
_expressionValue.Put(context, objectInstance);
return DefaultResult;
}
}

View file

@ -1,91 +0,0 @@
using System.Text.Json;
using Elsa.Workflows;
using Elsa.Workflows.Models;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
/// <inheritdoc />
public override IWorkflowBuilder VisitObjectExpr(ElsaParser.ObjectExprContext context)
{
VisitChildren(context);
var value = _expressionValue.Get(context.@object());
_expressionValue.Put(context, value);
return DefaultResult;
}
/// <inheritdoc />
public override IWorkflowBuilder VisitObjectStat(ElsaParser.ObjectStatContext context)
{
VisitChildren(context);
var value = _expressionValue.Get(context.@object());
_expressionValue.Put(context, value);
return DefaultResult;
}
/// <inheritdoc />
public override IWorkflowBuilder VisitObject(ElsaParser.ObjectContext context)
{
var @object = GetObjectAsync(context).GetAwaiter().GetResult();
_object.Put(context, @object);
_expressionValue.Put(context, @object);
VisitChildren(context);
return DefaultResult;
}
private async Task<object> GetObjectAsync(ElsaParser.ObjectContext context)
{
var objectTypeName = context.ID().GetText();
// First, check if the symbol matches an activity type.
var activityDescriptor = await _activityRegistryLookup.FindAsync(x => x.Name == objectTypeName);
if (activityDescriptor != null)
{
// TODO: Refactor this to remove the dependency on JsonElement and JsonSerializerOptions.
// This limits the ability to use this class in other contexts, such as constructing activities from the DSL.
var jsonElement = JsonSerializer.Deserialize<JsonElement>("{}");
var ctorArgs = new ActivityConstructorContext(activityDescriptor, jsonElement, new JsonSerializerOptions());
return activityDescriptor.Constructor(ctorArgs);
}
var objectTypeDescriptor = _typeSystem.ResolveTypeName(objectTypeName);
if (objectTypeDescriptor == null)
{
// Perhaps this is a variable reference?
if (_definedVariables.TryGetValue(objectTypeName, out var definedVariable))
{
_expressionValue.Put(context, definedVariable.Value);
return DefaultResult;
}
// Or a workflow variable?
var workflowVariableQuery =
from container in _containerStack
from variable in container.Variables
where variable.Name == objectTypeName
select variable;
var workflowVariable = workflowVariableQuery.FirstOrDefault();
if (workflowVariable != null)
{
_expressionValue.Put(context, workflowVariable);
return DefaultResult;
}
throw new Exception($"Unknown type: {objectTypeName}");
}
var objectType = objectTypeDescriptor.Type;
var @object = Activator.CreateInstance(objectType)!;
return @object;
}
}

View file

@ -1,65 +0,0 @@
using System.Reflection;
using Elsa.Expressions.Helpers;
using Elsa.Expressions.Models;
using Elsa.Workflows;
using Elsa.Workflows.Models;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
/// <inheritdoc />
public override IWorkflowBuilder VisitProperty(ElsaParser.PropertyContext context)
{
var @object = _object.Get(context.Parent.Parent.Parent);
var objectType = @object.GetType();
var propertyName = context.ID().GetText();
var propertyInfo = objectType.GetProperty(propertyName);
if (propertyInfo == null)
throw new Exception($"Type {objectType.Name} does not have a public property named {propertyName}.");
_expressionType.Put(context, propertyInfo.PropertyType);
VisitChildren(context);
var propertyValue = _expressionValue.Get(context.expr());
var propertyType = propertyInfo.PropertyType;
var parsedPropertyValue = typeof(Input).IsAssignableFrom(propertyType) ? propertyValue : propertyValue.ConvertTo(propertyType);
SetPropertyValue(@object, propertyInfo, parsedPropertyValue);
return DefaultResult;
}
private void SetPropertyValue(object target, PropertyInfo propertyInfo, object? value)
{
if (typeof(Input).IsAssignableFrom(propertyInfo.PropertyType))
value = CreateInputValue(propertyInfo, value);
propertyInfo.SetValue(target, value, null);
}
private Input CreateInputValue(PropertyInfo propertyInfo, object? propertyValue)
{
var underlyingType = propertyInfo.PropertyType.GetGenericArguments().First();
var parsedPropertyValue = propertyValue.ConvertTo(underlyingType);
var propertyValueType = parsedPropertyValue?.GetType();
var inputType = typeof(Input<>).MakeGenericType(underlyingType);
if (propertyValueType != null)
{
// Create a literal value.
var literalType = typeof(Literal<>).MakeGenericType(underlyingType);
var hasCtorWithSpecifiedType = inputType.GetConstructors().Any(x => x.GetParameters().Any(y => y.ParameterType.IsAssignableFrom(literalType)));
if (hasCtorWithSpecifiedType)
{
var literalValue = Activator.CreateInstance(literalType, parsedPropertyValue)!;
return (Input)Activator.CreateInstance(inputType, literalValue)!;
}
}
return parsedPropertyValue is ExternalExpressionReference externalExpressionReference
? (Input)Activator.CreateInstance(inputType, externalExpressionReference.Expression, externalExpressionReference.BlockReference)!
: (Input)Activator.CreateInstance(inputType, parsedPropertyValue)!;
}
}

View file

@ -1,20 +0,0 @@
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitStringValueExpr(ElsaParser.StringValueExprContext context)
{
var value = context.GetText().Trim('\"');
_expressionValue.Put(context, value);
return DefaultResult;
}
public override IWorkflowBuilder VisitBackTickStringValueExpr(ElsaParser.BackTickStringValueExprContext context)
{
var value = context.GetText().Trim('\"');
_expressionValue.Put(context, value);
return DefaultResult;
}
}

View file

@ -1,50 +0,0 @@
using Elsa.Workflows;
using Elsa.Workflows.Memory;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter
{
public override IWorkflowBuilder VisitVariableDeclarationStat(ElsaParser.VariableDeclarationStatContext context)
{
VisitChildren(context);
var expressionValue = _expressionValue.Get(context.varDecl());
_expressionValue.Put(context, expressionValue);
return DefaultResult;
}
public override IWorkflowBuilder VisitVarDecl(ElsaParser.VarDeclContext context)
{
var workflowVariableName = context.ID().GetText();
VisitChildren(context);
var initExpr = context.expr();
var workflowVariableValue = initExpr != null ? _expressionValue.Get(initExpr) : default;
var workflowVariable = new Variable
{
Name = workflowVariableName
};
if (workflowVariableValue is IActivity activity)
{
// When an activity is assigned to a workflow variable, what we really are doing is setting the variable to the activity's output.
var activityType = activity.GetType();
var outputProperty = activityType.GetProperties().FirstOrDefault(x => x.Name == "Result");
if (outputProperty == null)
throw new Exception("Cannot assign output of an activity that does not have an Output property.");
var outputValue = Activator.CreateInstance(outputProperty.PropertyType, workflowVariable, default);
outputProperty.SetValue(activity, outputValue);
_expressionValue.Put(context, activity);
}
var currentContainer = _containerStack.Peek();
currentContainer.Variables.Add(workflowVariable);
return DefaultResult;
}
}

View file

@ -1,37 +0,0 @@
using Antlr4.Runtime.Tree;
using Elsa.Expressions.Dsl.Contracts;
using Elsa.Expressions.Dsl.Models;
using Elsa.Workflows;
using Elsa.Workflows.Activities;
namespace Elsa.Expressions.Dsl.Interpreters;
public partial class WorkflowDefinitionBuilderInterpreter : ElsaParserBaseVisitor<IWorkflowBuilder>
{
private readonly ITypeSystem _typeSystem;
private readonly IActivityRegistryLookupService _activityRegistryLookup;
private readonly IFunctionActivityRegistry _functionActivityRegistry;
private readonly IWorkflowBuilder _workflowBuilder;
private readonly ParseTreeProperty<object> _object = new();
private readonly ParseTreeProperty<object?> _expressionValue = new();
private readonly ParseTreeProperty<IList<object?>> _argValues = new();
private readonly ParseTreeProperty<Type> _expressionType = new();
private readonly IDictionary<string, DefinedVariable> _definedVariables = new Dictionary<string, DefinedVariable>();
private readonly Stack<Container> _containerStack = new();
/// <inheritdoc />
public WorkflowDefinitionBuilderInterpreter(
ITypeSystem typeSystem,
IActivityRegistryLookupService activityRegistryLookup,
IFunctionActivityRegistry functionActivityRegistry,
IWorkflowBuilderFactory workflowBuilderFactory)
{
_typeSystem = typeSystem;
_activityRegistryLookup = activityRegistryLookup;
_functionActivityRegistry = functionActivityRegistry;
_workflowBuilder = workflowBuilderFactory.CreateBuilder();
}
/// <inheritdoc />
protected override IWorkflowBuilder DefaultResult => _workflowBuilder;
}

View file

@ -1,8 +0,0 @@
namespace Elsa.Expressions.Dsl.Models;
public class DefinedVariable
{
public string Identifier { get; set; } = default!;
public Type Type { get; set; } = default!;
public object? Value { get; set; }
}

View file

@ -1,12 +0,0 @@
using Elsa.Workflows;
namespace Elsa.Expressions.Dsl.Models;
/// <summary>
/// Describes a function that is mapped to an activity that can be invoked from a DSL script.
/// </summary>
/// <param name="FunctionName">The name of the function.</param>
/// <param name="ActivityTypeName">The name of the activity type.</param>
/// <param name="PropertyNames">The names of the properties that are mapped to the function arguments.</param>
/// <param name="Configure">An optional action that can be used to configure the activity.</param>
public record FunctionActivityDescriptor(string FunctionName, string ActivityTypeName, IEnumerable<string>? PropertyNames = default, Action<IActivity>? Configure = default);

View file

@ -1,5 +0,0 @@
namespace Elsa.Expressions.Dsl.Models;
public class WorkflowDefinitionInterpreterSettings
{
}

View file

@ -1,52 +0,0 @@
using Antlr4.Runtime;
using Elsa.Expressions.Dsl.Contracts;
using Elsa.Expressions.Dsl.Interpreters;
using Elsa.Workflows;
using Elsa.Workflows.Activities;
namespace Elsa.Expressions.Dsl.Services;
/// <inheritdoc />
public class DslEngine : IDslEngine
{
private readonly ITypeSystem _typeSystem;
private readonly IActivityRegistryLookupService _activityRegistryLookup;
private readonly IFunctionActivityRegistry _functionActivityRegistry;
private readonly IWorkflowBuilderFactory _workflowBuilderFactory;
/// <summary>
/// Initializes a new instance of the <see cref="DslEngine"/> class.
/// </summary>
public DslEngine(
ITypeSystem typeSystem,
IActivityRegistryLookupService activityRegistryLookup,
IFunctionActivityRegistry functionActivityRegistry,
IWorkflowBuilderFactory workflowBuilderFactory)
{
_typeSystem = typeSystem;
_activityRegistryLookup = activityRegistryLookup;
_functionActivityRegistry = functionActivityRegistry;
_workflowBuilderFactory = workflowBuilderFactory;
}
/// <inheritdoc />
public async Task<Workflow> ParseAsync(string script, CancellationToken cancellationToken = default)
{
var stream = CharStreams.fromString(script);
var lexer = new ElsaLexer(stream);
var tokens = new CommonTokenStream(lexer);
var parser = new ElsaParser(tokens);
var tree = parser.program();
var interpreter = new WorkflowDefinitionBuilderInterpreter(
_typeSystem,
_activityRegistryLookup,
_functionActivityRegistry,
_workflowBuilderFactory);
var workflowBuilder = interpreter.Visit(tree);
var workflow = await workflowBuilder.BuildWorkflowAsync(cancellationToken);
return workflow;
}
}

View file

@ -1,139 +0,0 @@
using System.Text.Json;
using Elsa.Expressions.Dsl.Contracts;
using Elsa.Expressions.Dsl.Interpreters;
using Elsa.Expressions.Dsl.Models;
using Elsa.Expressions.Helpers;
using Elsa.Expressions.Models;
using Elsa.Workflows;
using Elsa.Workflows.Models;
namespace Elsa.Expressions.Dsl.Services;
/// <inheritdoc />
public class FunctionActivityRegistry : IFunctionActivityRegistry
{
private readonly IActivityRegistryLookupService _activityRegistryLookup;
private readonly IDictionary<string, FunctionActivityDescriptor> _dictionary = new Dictionary<string, FunctionActivityDescriptor>();
/// <summary>
/// Creates a new instance of the <see cref="FunctionActivityRegistry"/> class.
/// </summary>
public FunctionActivityRegistry(IActivityRegistryLookupService activityRegistryLookup)
{
_activityRegistryLookup = activityRegistryLookup;
}
/// <inheritdoc />
public void RegisterFunction(string functionName, string activityTypeName, IEnumerable<string>? propertyNames = default, Action<IActivity>? configure = default)
{
var descriptor = new FunctionActivityDescriptor(functionName, activityTypeName, propertyNames, configure);
RegisterFunction(descriptor);
}
/// <inheritdoc />
public void RegisterFunction(FunctionActivityDescriptor descriptor)
{
_dictionary.Add(descriptor.FunctionName, descriptor);
}
/// <inheritdoc />
public async Task<IActivity> ResolveFunctionAsync(string functionName, IEnumerable<object?>? arguments = default)
{
if (!_dictionary.TryGetValue(functionName, out var descriptor))
throw new Exception($"Could not resolve function {functionName}. Did you forget to register it?");
var activityDescriptor = await _activityRegistryLookup.FindAsync(x => x.Name == descriptor.ActivityTypeName || x.TypeName == descriptor.ActivityTypeName);
if (activityDescriptor == null)
throw new Exception($"Could not find activity descriptor for activity type {descriptor.ActivityTypeName}");
var propertyNameList = descriptor.PropertyNames?.ToList() ?? new List<string>();
var propertyDescriptors = activityDescriptor.Inputs.Cast<PropertyDescriptor>().Concat(activityDescriptor.Outputs).ToList();
var properties = propertyNameList
.Select(propertyName => propertyDescriptors.FirstOrDefault(x => x.Name == propertyName))
.Where(x => x != null)
.Select(x => x!)
.ToList();
var dummyJsonElement = JsonDocument.Parse("{}").RootElement;
var constructorContext = new ActivityConstructorContext(activityDescriptor, dummyJsonElement, new JsonSerializerOptions());
var activity = activityDescriptor.Constructor(constructorContext);
// Apply each argument in order of the described properties.
var index = 0;
if (arguments != null)
foreach (var argument in arguments)
{
var property = properties[index++];
SetPropertyValue(activity, property, argument);
}
descriptor.Configure?.Invoke(activity);
return activity;
}
private void SetPropertyValue(IActivity target, PropertyDescriptor propertyDescriptor, object? value)
{
value = propertyDescriptor switch
{
InputDescriptor inputDescriptor => CreateInputValue(inputDescriptor, value),
OutputDescriptor outputDescriptor => CreateOutputValue(outputDescriptor, value),
_ => value
};
propertyDescriptor.ValueSetter(target, value);
}
private Input CreateInputValue(InputDescriptor inputDescriptor, object? propertyValue)
{
if (propertyValue is Input input)
return input;
var underlyingType = inputDescriptor.Type;
var parsedPropertyValue = propertyValue.ConvertTo(underlyingType);
var propertyValueType = parsedPropertyValue?.GetType();
var inputType = typeof(Input<>).MakeGenericType(underlyingType);
if (parsedPropertyValue is ExternalExpressionReference externalExpressionReference)
return (Input)Activator.CreateInstance(inputType, externalExpressionReference.Expression, externalExpressionReference.BlockReference)!;
if (propertyValueType != null)
{
// Create a literal value.
var literalType = typeof(Literal<>).MakeGenericType(underlyingType);
var hasCtorWithSpecifiedType = inputType.GetConstructors().Any(x => x.GetParameters().Any(y => y.ParameterType.IsAssignableFrom(literalType)));
if (hasCtorWithSpecifiedType)
{
var literalValue = Activator.CreateInstance(literalType, parsedPropertyValue)!;
return (Input)Activator.CreateInstance(inputType, literalValue)!;
}
}
return (Input)Activator.CreateInstance(inputType, parsedPropertyValue)!;
}
private Output CreateOutputValue(OutputDescriptor outputDescriptor, object? propertyValue)
{
if (propertyValue is Output output)
return output;
var underlyingType = outputDescriptor.Type;
var propertyValueType = propertyValue?.GetType();
var outputType = typeof(Output<>).MakeGenericType(underlyingType);
if (propertyValueType != null)
{
var hasCtorWithSpecifiedType = outputType.GetConstructors().Any(x => x.GetParameters().Any(y => y.ParameterType.IsAssignableFrom(propertyValueType)));
if (hasCtorWithSpecifiedType)
return (Output)Activator.CreateInstance(outputType, propertyValue, null)!;
}
var convertedValue = propertyValue.ConvertTo(underlyingType);
return (Output)Activator.CreateInstance(outputType, convertedValue)!;
}
}

View file

@ -1,19 +0,0 @@
using Elsa.Expressions.Dsl.Contracts;
using Elsa.Workflows.Models;
namespace Elsa.Expressions.Dsl.Services;
public class TypeSystem : ITypeSystem
{
private readonly IDictionary<string, TypeDescriptor> _typeNameLookup = new Dictionary<string, TypeDescriptor>();
private readonly IDictionary<Type, TypeDescriptor> _typeLookup = new Dictionary<Type, TypeDescriptor>();
public void Register(TypeDescriptor descriptor)
{
_typeNameLookup[descriptor.Name] = descriptor;
_typeLookup[descriptor.Type] = descriptor;
}
public TypeDescriptor? ResolveTypeName(string typeName) => _typeNameLookup.TryGetValue(typeName, out var descriptor) ? descriptor : default;
public TypeDescriptor? ResolveType(Type type) => _typeLookup.TryGetValue(type, out var descriptor) ? descriptor : default;
}

View file

@ -2,7 +2,7 @@ namespace Elsa.Identity.Endpoints.Applications.Create;
internal class Request
{
public string Name { get; set; } = default!;
public string Name { get; set; } = null!;
public ICollection<string>? Roles { get; set; }
}

View file

@ -2,6 +2,6 @@ namespace Elsa.Identity.Endpoints.Login;
public class Request
{
public string Username { get; set; } = default!;
public string Password { get; set; } = default!;
public string Username { get; set; } = null!;
public string Password { get; set; } = null!;
}

View file

@ -2,8 +2,8 @@ namespace Elsa.Identity.Endpoints.Roles.Create;
internal class Request
{
public string? Id { get; set; } = default!;
public string Name { get; set; } = default!;
public string? Id { get; set; } = null!;
public string Name { get; set; } = null!;
public ICollection<string>? Permissions { get; set; }
}

View file

@ -4,7 +4,7 @@ namespace Elsa.Identity.Endpoints.Secrets.Hash;
internal class Request
{
[Required] public string Secret { get; set; } = default!;
[Required] public string Secret { get; set; } = null!;
}
internal class Response

View file

@ -2,7 +2,7 @@ namespace Elsa.Identity.Endpoints.Users.Create;
internal class Request
{
public string Name { get; set; } = default!;
public string Name { get; set; } = null!;
public string? Password { get; set; }
public ICollection<string>? Roles { get; set; }
}

View file

@ -10,32 +10,32 @@ public class Application : Entity
/// <summary>
/// The client ID.
/// </summary>
public string ClientId { get; set; } = default!;
public string ClientId { get; set; } = null!;
/// <summary>
/// The hashed client secret.
/// </summary>
public string HashedClientSecret { get; set; } = default!;
public string HashedClientSecret { get; set; } = null!;
/// <summary>
/// The hashed client secret salt.
/// </summary>
public string HashedClientSecretSalt { get; set; } = default!;
public string HashedClientSecretSalt { get; set; } = null!;
/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name { get; set; } = default!;
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the hashed password.
/// </summary>
public string HashedApiKey { get; set; } = default!;
public string HashedApiKey { get; set; } = null!;
/// <summary>
/// Gets or sets the hashed password salt.
/// </summary>
public string HashedApiKeySalt { get; set; } = default!;
public string HashedApiKeySalt { get; set; } = null!;
/// <summary>
/// Gets or sets the roles.

View file

@ -10,7 +10,7 @@ public class Role : Entity
/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name { get; set; } = default!;
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the permissions.

View file

@ -10,17 +10,17 @@ public class User : Entity
/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name { get; set; } = default!;
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the hashed password.
/// </summary>
public string HashedPassword { get; set; } = default!;
public string HashedPassword { get; set; } = null!;
/// <summary>
/// Gets or sets the hashed password salt.
/// </summary>
public string HashedPasswordSalt { get; set; } = default!;
public string HashedPasswordSalt { get; set; } = null!;
/// <summary>
/// Gets or sets the roles.

View file

@ -12,7 +12,7 @@ public static class ModuleExtensions
/// <summary>
/// Installs & configures the <see cref="IdentityFeature"/> feature.
/// </summary>
public static IModule UseIdentity(this IModule module, Action<IdentityFeature> configure)
public static IModule UseIdentity(this IModule module, Action<IdentityFeature>? configure = null)
{
module.Configure(configure);
return module;
@ -21,7 +21,7 @@ public static class ModuleExtensions
/// <summary>
/// Installs & configures the <see cref="IdentityFeature"/> feature.
/// </summary>
public static IModule UseIdentity(this IModule module, string signingKey, string issuer = "http://elsa.api", string audience = "http://elsa.api", TimeSpan? tokenLifetime = default)
public static IModule UseIdentity(this IModule module, string signingKey, string issuer = "http://elsa.api", string audience = "http://elsa.api", TimeSpan? tokenLifetime = null)
{
module.UseIdentity(identity => identity.TokenOptions += options =>
{
@ -36,7 +36,7 @@ public static class ModuleExtensions
/// <summary>
/// Installs & configures the <see cref="IdentityFeature"/> feature.
/// </summary>
public static IModule UseDefaultAuthentication(this IModule module, Action<DefaultAuthenticationFeature>? configure = default)
public static IModule UseDefaultAuthentication(this IModule module, Action<DefaultAuthenticationFeature>? configure = null)
{
module.Configure(configure);
return module;

View file

@ -14,7 +14,7 @@ public class IdentityTokenOptions
/// <summary>
/// The key to use when signing tokens
/// </summary>
public string SigningKey { get; set; } = default!;
public string SigningKey { get; set; } = null!;
/// <summary>
/// The issuer to use when creating and validating tokens

View file

@ -27,15 +27,15 @@ public class DefaultApplicationCredentialsValidator : IApplicationCredentialsVal
public async ValueTask<Application?> ValidateAsync(string apiKey, CancellationToken cancellationToken = default)
{
if(string.IsNullOrWhiteSpace(apiKey))
return default;
return null;
var clientId = _apiKeyParser.Parse(apiKey);
var application = await _applicationProvider.FindByClientIdAsync(clientId, cancellationToken);
if(application == null)
return default;
return null;
var isValidApiKey = _secretHasher.VerifySecret(apiKey, application.HashedApiKey, application.HashedApiKeySalt);
return isValidApiKey ? application : default;
return isValidApiKey ? application : null;
}
}

View file

@ -27,10 +27,10 @@ public class DefaultUserCredentialsValidator : IUserCredentialsValidator
var user = await _userProvider.FindByNameAsync(username, cancellationToken);
if (user == null)
return default;
return null;
var isValidPassword = _secretHasher.VerifySecret(password, user.HashedPassword, user.HashedPasswordSalt);
return isValidPassword ? user : default;
return isValidPassword ? user : null;
}
}

View file

@ -0,0 +1,66 @@
using System.Runtime.CompilerServices;
using Elsa.Extensions;
using Elsa.Scheduling.Bookmarks;
using Elsa.Workflows;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Models;
namespace Elsa.Scheduling.Activities;
/// <summary>
/// Represents a timer to periodically trigger the workflow.
/// </summary>
[Activity("Elsa", "Scheduling", "Trigger workflow execution at a specific interval using a CRON expression.")]
public class Cron : EventGenerator
{
/// <inheritdoc />
public Cron([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
}
/// <inheritdoc />
public Cron(string cronExpression, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(new Input<string>(cronExpression), source, line)
{
}
/// <inheritdoc />
public Cron(Input<string> cronExpression, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line)
{
CronExpression = cronExpression;
}
/// <summary>
/// The interval at which the timer should execute.
/// </summary>
[Input(Description = "The CRON expression at which the timer should execute.")]
public Input<string> CronExpression { get; set; } = null!;
/// <inheritdoc />
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
if(context.IsTriggerOfWorkflow())
{
await context.CompleteActivityAsync();
return;
}
var cronParser = context.GetRequiredService<ICronParser>();
var cronExpression = context.ExpressionExecutionContext.Get(CronExpression)!;
var executeAt = cronParser.GetNextOccurrence(cronExpression);
context.JournalData.Add("ExecuteAt", executeAt);
context.CreateBookmark(new CronBookmarkPayload(executeAt, cronExpression));
}
/// <inheritdoc />
protected override object GetTriggerPayload(TriggerIndexingContext context)
{
var cronExpression = context.ExpressionExecutionContext.Get(CronExpression)!;
return new CronTriggerPayload(cronExpression);
}
/// <summary>
/// Creates a new <see cref="Cron"/> activity set to trigger at the specified cron expression.
/// </summary>
public static Cron FromCronExpression(string value, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(value, source, line);
}

View file

@ -0,0 +1,113 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using Elsa.Expressions.Models;
using Elsa.Extensions;
using Elsa.Workflows;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Memory;
using Elsa.Workflows.Models;
namespace Elsa.Scheduling.Activities;
/// <summary>
/// Delay execution for the specified amount of time.
/// </summary>
[Activity("Elsa", "Scheduling", "Delay execution for the specified amount of time.")]
public class Delay : Activity, IActivityPropertyDefaultValueProvider
{
/// <inheritdoc />
public Delay([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
}
/// <inheritdoc />
public Delay(
Func<ExpressionExecutionContext, TimeSpan> timeSpan,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(new Input<TimeSpan>(timeSpan), source, line)
{
}
/// <inheritdoc />
public Delay(
Func<ExpressionExecutionContext, ValueTask<TimeSpan>> timeSpan,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(new Input<TimeSpan>(timeSpan), source, line)
{
}
/// <inheritdoc />
public Delay(
Input<TimeSpan> timeSpan,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
TimeSpan = timeSpan;
}
/// <inheritdoc />
public Delay(
TimeSpan timeSpan,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
TimeSpan = new Input<TimeSpan>(timeSpan);
}
/// <inheritdoc />
public Delay(
Variable<TimeSpan> timeSpan,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
TimeSpan = new Input<TimeSpan>(timeSpan);
}
/// <summary>
/// The amount of time to delay execution.
/// </summary>
[Input(
Description = "The timespan to delay workflow execution.",
DefaultValueProvider = typeof(Delay)
)]
public Input<TimeSpan> TimeSpan { get; set; } = null!;
/// <inheritdoc />
protected override void Execute(ActivityExecutionContext context)
{
var timeSpan = context.ExpressionExecutionContext.Get(TimeSpan);
context.DelayFor(timeSpan);
}
/// <summary>
/// Creates a new <see cref="Delay"/> from the specified number of milliseconds.
/// </summary>
public static Delay FromMilliseconds(
double value,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(System.TimeSpan.FromMilliseconds(value), source, line);
/// <summary>
/// Creates a new <see cref="Delay"/> from the specified number of seconds.
/// </summary>
public static Delay FromSeconds(
double value,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(System.TimeSpan.FromSeconds(value), source, line);
/// <summary>
/// Creates a new <see cref="Delay"/> from the specified number of minutes.
/// </summary>
public static Delay FromMinutes(
double value,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(System.TimeSpan.FromMinutes(value), source, line);
/// <summary>
/// Creates a new <see cref="Delay"/> from the specified number of hours.
/// </summary>
public static Delay FromHours(
double value,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(System.TimeSpan.FromHours(value), source, line);
/// <summary>
/// Creates a new <see cref="Delay"/> from the specified number of days.
/// </summary>
public static Delay FromDays(
double value,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(System.TimeSpan.FromDays(value), source, line);
object IActivityPropertyDefaultValueProvider.GetDefaultValue(PropertyInfo property) => System.TimeSpan.FromMinutes(1);
}

View file

@ -0,0 +1,107 @@
using System.Runtime.CompilerServices;
using Elsa.Common;
using Elsa.Expressions.Models;
using Elsa.Extensions;
using Elsa.Scheduling.Bookmarks;
using Elsa.Workflows;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Memory;
using Elsa.Workflows.Models;
using Microsoft.Extensions.Logging;
namespace Elsa.Scheduling.Activities;
/// <summary>
/// Triggers the workflow at a specific future timestamp.
/// </summary>
[Activity("Elsa", "Scheduling", "Trigger execution at a specific time in the future.")]
public class StartAt : Trigger
{
private const string InputKey = "ExecuteAt";
/// <inheritdoc />
public StartAt([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
}
/// <inheritdoc />
public StartAt(Input<DateTimeOffset> dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line) => DateTime = dateTime;
/// <inheritdoc />
public StartAt(Func<ExpressionExecutionContext, DateTimeOffset> dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null)
: this(new Input<DateTimeOffset>(dateTime), source, line)
{
}
/// <inheritdoc />
public StartAt(
Func<ExpressionExecutionContext, ValueTask<DateTimeOffset>> dateTime,
[CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(new Input<DateTimeOffset>(dateTime), source, line)
{
}
/// <inheritdoc />
public StartAt(Func<ValueTask<DateTimeOffset>> dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null)
: this(new Input<DateTimeOffset>(dateTime), source, line)
{
}
/// <inheritdoc />
public StartAt(Func<DateTimeOffset> dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null)
: this(new Input<DateTimeOffset>(dateTime), source, line)
{
}
/// <inheritdoc />
public StartAt(DateTimeOffset dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line) =>
DateTime = new Input<DateTimeOffset>(dateTime);
/// <inheritdoc />
public StartAt(Variable<DateTimeOffset> dateTime, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line) =>
DateTime = new Input<DateTimeOffset>(dateTime);
/// <summary>
/// The timestamp at which the workflow should be triggered.
/// </summary>
[Input]
public Input<DateTimeOffset> DateTime { get; set; } = null!;
/// <inheritdoc />
protected override object GetTriggerPayload(TriggerIndexingContext context)
{
var executeAt = context.ExpressionExecutionContext.Get(DateTime);
return new StartAtPayload(executeAt);
}
/// <inheritdoc />
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
if (context.IsTriggerOfWorkflow())
{
await context.CompleteActivityAsync();
return;
}
var executeAt = context.ExpressionExecutionContext.Get(DateTime);
var clock = context.ExpressionExecutionContext.GetRequiredService<ISystemClock>();
var now = clock.UtcNow;
var logger = context.GetRequiredService<ILogger<StartAt>>();
context.JournalData.Add("Executed At", now);
if (executeAt <= now)
{
logger.LogDebug("Scheduled trigger time lies in the past ('{Delta}'). Completing immediately", now - executeAt);
await context.CompleteActivityAsync();
return;
}
var payload = new StartAtPayload(executeAt);
context.CreateBookmark(payload);
}
/// <summary>
/// Creates a new <see cref="StartAt"/> activity set to trigger at the specified timestamp.
/// </summary>
public static StartAt From(DateTimeOffset value, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(value, source, line);
}

View file

@ -0,0 +1,51 @@
using System.Runtime.CompilerServices;
using Elsa.Expressions.Models;
using Elsa.Extensions;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Models;
namespace Elsa.Scheduling.Activities;
/// <summary>
/// Represents a timer to periodically trigger the workflow.
/// </summary>
[Activity("Elsa", "Scheduling", "Trigger workflow execution at a specific interval.")]
public class Timer : TimerBase
{
/// <inheritdoc />
public Timer([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
}
/// <inheritdoc />
public Timer(TimeSpan interval, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(new Input<TimeSpan>(interval), source, line)
{
}
/// <inheritdoc />
public Timer(Input<TimeSpan> interval, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : this(source, line)
{
Interval = interval;
}
/// <summary>
/// The interval at which the timer should execute.
/// </summary>
[Input(Description = "The interval at which the timer should execute.", DefaultValue = "00:01:00")]
public Input<TimeSpan> Interval { get; set; } = new(TimeSpan.FromMinutes(1));
protected override TimeSpan GetInterval(ExpressionExecutionContext context)
{
return Interval.Get(context);
}
/// <summary>
/// Creates a new <see cref="Timer"/> activity set to trigger at the specified interval.
/// </summary>
public static Timer FromTimeSpan(TimeSpan value, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => new(value, source, line);
/// <summary>
/// Creates a new <see cref="Timer"/> activity set to trigger at the specified interval in seconds.
/// </summary>
public static Timer FromSeconds(double value, [CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) => FromTimeSpan(TimeSpan.FromSeconds(value), source, line);
}

View file

@ -0,0 +1,43 @@
using System.Runtime.CompilerServices;
using Elsa.Expressions.Models;
using Elsa.Extensions;
using Elsa.Workflows;
namespace Elsa.Scheduling.Activities;
/// <summary>
/// </summary>
public abstract class TimerBase([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : EventGenerator(source, line)
{
protected abstract TimeSpan GetInterval(ExpressionExecutionContext context);
protected virtual ValueTask OnTimerElapsedAsync(ActivityExecutionContext context)
{
OnTimerElapsed(context);
return default;
}
protected virtual void OnTimerElapsed(ActivityExecutionContext context)
{
}
/// <inheritdoc />
protected override void Execute(ActivityExecutionContext context)
{
var interval = GetInterval(context.ExpressionExecutionContext);
context.RepeatWithInterval(interval, TimerElapsedAsync);
}
/// <inheritdoc />
protected override object GetTriggerPayload(TriggerIndexingContext context)
{
var interval = GetInterval(context.ExpressionExecutionContext);
return context.GetTimerTriggerStimulus(interval);
}
private async ValueTask TimerElapsedAsync(ActivityExecutionContext context)
{
await OnTimerElapsedAsync(context);
await context.CompleteActivityAsync();
}
}

View file

@ -0,0 +1,3 @@
namespace Elsa.Scheduling.Bookmarks;
internal record CronBookmarkPayload(DateTimeOffset ExecuteAt, string CronExpression);

View file

@ -0,0 +1,3 @@
namespace Elsa.Scheduling.Bookmarks;
public record CronTriggerPayload(string CronExpression);

View file

@ -0,0 +1,8 @@
using Elsa.Scheduling.Activities;
namespace Elsa.Scheduling.Bookmarks;
/// <summary>
/// A bookmark payload for <see cref="Delay"/>.
/// </summary>
public record DelayPayload(DateTimeOffset ResumeAt);

View file

@ -0,0 +1,3 @@
namespace Elsa.Scheduling.Bookmarks;
internal record StartAtPayload(DateTimeOffset ExecuteAt);

View file

@ -0,0 +1,3 @@
namespace Elsa.Scheduling.Bookmarks;
internal record TimerBookmarkPayload(DateTimeOffset ResumeAt);

View file

@ -0,0 +1,3 @@
namespace Elsa.Scheduling.Bookmarks;
public record TimerTriggerPayload(DateTimeOffset StartAt, TimeSpan Interval);

View file

@ -0,0 +1,8 @@
using Elsa.Mediator.Contracts;
namespace Elsa.Scheduling.Commands;
/// <summary>
/// A command to run a scheduled task.
/// </summary>
public record RunScheduledTask(ITask Task) : ICommand;

View file

@ -0,0 +1,39 @@
using Elsa.Workflows.Models;
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.Scheduling;
/// <summary>
/// Creates timer schedules for the specified bookmarks.
/// </summary>
public interface IBookmarkScheduler
{
/// <summary>
/// Schedules the specified list of bookmarks.
/// </summary>
/// <param name="bookmarks">The bookmarks to schedule.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
Task ScheduleAsync(IEnumerable<StoredBookmark> bookmarks, CancellationToken cancellationToken = default);
/// <summary>
/// Schedules the specified list of bookmarks.
/// </summary>
/// <param name="workflowInstanceId">The ID of the workflow instance to which the bookmarks belong.</param>
/// <param name="bookmarks">The bookmarks to schedule.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
Task ScheduleAsync(string workflowInstanceId, IEnumerable<Bookmark> bookmarks, CancellationToken cancellationToken = default);
/// <summary>
/// Unschedules the specified list of bookmarks.
/// </summary>
/// <param name="bookmarks">The bookmarks to unschedule.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
Task UnscheduleAsync(IEnumerable<Bookmark> bookmarks, CancellationToken cancellationToken = default);
/// <summary>
/// Unschedules the specified list of bookmarks.
/// </summary>
/// <param name="bookmarks">The bookmarks to unschedule.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
Task UnscheduleAsync(IEnumerable<StoredBookmark> bookmarks, CancellationToken cancellationToken = default);
}

View file

@ -0,0 +1,13 @@
namespace Elsa.Scheduling;
/// <summary>Represents a cron expression parser.</summary>
/// <remarks>The providers can support different formats. Quartz, for example, supports years.</remarks>
public interface ICronParser
{
/// <summary>
/// Converts a provider dependent cron expression to a <see cref="DateTimeOffset"/>.
/// </summary>
/// <param name="expression">The cron expression to parse.</param>
/// <returns>The next occurrence.</returns>
DateTimeOffset GetNextOccurrence(string expression);
}

View file

@ -0,0 +1,14 @@
namespace Elsa.Scheduling;
/// <summary>
/// A schedule that can be used to schedule a task.
/// </summary>
public interface ISchedule
{
/// <summary>
/// Create a scheduled task.
/// </summary>
/// <param name="context">The context.</param>
/// <returns>The scheduled task.</returns>
IScheduledTask Schedule(ScheduleContext context);
}

View file

@ -0,0 +1,12 @@
namespace Elsa.Scheduling;
/// <summary>
/// Represents a scheduled task.
/// </summary>
public interface IScheduledTask
{
/// <summary>
/// Cancels the scheduled task.
/// </summary>
void Cancel();
}

View file

@ -0,0 +1,40 @@
namespace Elsa.Scheduling;
/// <summary>
/// Schedules tasks.
/// </summary>
public interface IScheduler
{
/// <summary>
/// Schedules a task using the specified schedule.
/// </summary>
/// <param name="name">The name of the task to schedule.</param>
/// <param name="task">The task to schedule.</param>
/// <param name="schedule">The schedule to use.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleAsync(string name, ITask task, ISchedule schedule, CancellationToken cancellationToken = default);
/// <summary>
/// Schedules a task using the specified schedule.
/// </summary>
/// <param name="name">The name of the task to schedule.</param>
/// <param name="task">The task to schedule.</param>
/// <param name="schedule">The schedule to use.</param>
/// <param name="keys">A list of keys to associate with the task.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleAsync(string name, ITask task, ISchedule schedule, IEnumerable<string>? keys = null, CancellationToken cancellationToken = default);
/// <summary>
/// Unschedules the task with the specified name.
/// </summary>
/// <param name="name">The name of the task to unschedule.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ClearScheduleAsync(string name, CancellationToken cancellationToken = default);
/// <summary>
/// Unschedules tasks with the specified keys.
/// </summary>
/// <param name="keys">The keys of the tasks to unschedule.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ClearScheduleAsync(IEnumerable<string> keys, CancellationToken cancellationToken = default);
}

View file

@ -0,0 +1,12 @@
namespace Elsa.Scheduling;
/// <summary>
/// Represents a task.
/// </summary>
public interface ITask
{
/// <summary>
/// Executes the task.
/// </summary>
ValueTask ExecuteAsync(TaskExecutionContext context);
}

View file

@ -0,0 +1,23 @@
using Elsa.Workflows.Runtime.Entities;
namespace Elsa.Scheduling;
/// <summary>
/// Schedules tasks for the specified list of triggers.
/// </summary>
public interface ITriggerScheduler
{
/// <summary>
/// Schedules tasks for the specified list of triggers.
/// </summary>
/// <param name="triggers">The triggers to schedule tasks for.</param>
/// <param name="cancellationToken">The cancellation token.</param>
Task ScheduleAsync(IEnumerable<StoredTrigger> triggers, CancellationToken cancellationToken = default);
/// <summary>
/// Unschedules tasks for the specified list of triggers.
/// </summary>
/// <param name="triggers">The triggers to unschedule tasks for.</param>
/// <param name="cancellationToken">The cancellation token.</param>
Task UnscheduleAsync(IEnumerable<StoredTrigger> triggers, CancellationToken cancellationToken = default);
}

View file

@ -0,0 +1,70 @@
namespace Elsa.Scheduling;
/// <summary>
/// A contract for scheduling workflows to execute at a specific future instant. Can be used to implement a custom scheduler, e.g. using Quartz.NET and Hangfire.
/// </summary>
public interface IWorkflowScheduler
{
/// <summary>
/// Schedules a workflow request to be executed at the specified time.
/// </summary>
/// <param name="taskName">The name of the task to schedule.</param>
/// <param name="request">The workflow request to schedule.</param>
/// <param name="at">The time at which the workflow should be executed.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleAtAsync(string taskName, ScheduleNewWorkflowInstanceRequest request, DateTimeOffset at, CancellationToken cancellationToken = default);
/// <summary>
/// Schedules a workflow request to be executed at the specified time.
/// </summary>
/// <param name="taskName">The name of the task to schedule.</param>
/// <param name="request">The workflow request to schedule.</param>
/// <param name="at">The time at which the workflow should be executed.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleAtAsync(string taskName, ScheduleExistingWorkflowInstanceRequest request, DateTimeOffset at, CancellationToken cancellationToken = default);
/// <summary>
/// Schedules a workflow request to be executed at the specified time.
/// </summary>
/// <param name="taskName">The name of the task to schedule.</param>
/// <param name="request">The workflow request to schedule.</param>
/// <param name="startAt">The time at which the first execution should occur.</param>
/// <param name="interval">The interval at which the workflow should be executed.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleRecurringAsync(string taskName, ScheduleNewWorkflowInstanceRequest request, DateTimeOffset startAt, TimeSpan interval, CancellationToken cancellationToken = default);
/// <summary>
/// Schedules a workflow request to be executed at the specified time.
/// </summary>
/// <param name="taskName">The name of the task to schedule.</param>
/// <param name="request">The workflow request to schedule.</param>
/// <param name="startAt">The time at which the first execution should occur.</param>
/// <param name="interval">The interval at which the workflow should be executed.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleRecurringAsync(string taskName, ScheduleExistingWorkflowInstanceRequest request, DateTimeOffset startAt, TimeSpan interval, CancellationToken cancellationToken = default);
/// <summary>
/// Schedules a workflow request to be executed at the specified time.
/// </summary>
/// <param name="taskName">The name of the task to schedule.</param>
/// <param name="request">The workflow request to schedule.</param>
/// <param name="cronExpression">The cron expression to use.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleCronAsync(string taskName, ScheduleNewWorkflowInstanceRequest request, string cronExpression, CancellationToken cancellationToken = default);
/// <summary>
/// Schedules a workflow request to be executed at the specified time.
/// </summary>
/// <param name="taskName">The name of the task to schedule.</param>
/// <param name="request">The workflow request to schedule.</param>
/// <param name="cronExpression">The cron expression to use.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask ScheduleCronAsync(string taskName, ScheduleExistingWorkflowInstanceRequest request, string cronExpression, CancellationToken cancellationToken = default);
/// <summary>
/// Clears the schedule for the specified task.
/// </summary>
/// <param name="taskName">The name of the task to unschedule.</param>
/// <param name="cancellationToken">The cancellation token.</param>
ValueTask UnscheduleAsync(string taskName, CancellationToken cancellationToken = default);
}

View file

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>
Provides scheduling activities such as Timer, Delay and StartAt.
</Description>
<PackageTags>elsa extension module scheduling</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Cronos" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Elsa.Workflows.Runtime\Elsa.Workflows.Runtime.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=contracts/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=requests/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -0,0 +1,45 @@
using Elsa.Common;
using Elsa.Scheduling;
using Elsa.Scheduling.Bookmarks;
using Elsa.Workflows;
using Elsa.Workflows.Models;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
public static class DelayActivityExecutionContextExtensions
{
/// <summary>
/// Resumes the activity after a specified delay.
/// </summary>
/// <param name="context">The activity execution context in which the workflow is running.</param>
/// <param name="delay">The delay before the workflow resumes.</param>
/// <param name="callback">The delegate to execute when the activity resumes.</param>
public static void DelayFor(this ActivityExecutionContext context, TimeSpan delay, ExecuteActivityDelegate? callback = null)
{
var clock = context.ExpressionExecutionContext.GetRequiredService<ISystemClock>();
var resumeAt = clock.UtcNow.Add(delay);
DelayUntil(context, resumeAt, callback);
}
/// <summary>
/// Resumes the activity at a specified point in time.
/// </summary>
/// <param name="context">The activity execution context in which the workflow is running.</param>
/// <param name="resumeAt">The point in time at which the workflow should resume execution.</param>
/// <param name="callback">The delegate to execute when the activity resumes.</param>
public static void DelayUntil(this ActivityExecutionContext context, DateTimeOffset resumeAt, ExecuteActivityDelegate? callback = null)
{
var payload = new DelayPayload(resumeAt);
var bookmarkOptions = new CreateBookmarkArgs
{
BookmarkName = SchedulingStimulusNames.Delay,
Stimulus = payload,
Callback = callback
};
context.CreateBookmark(bookmarkOptions);
}
}

View file

@ -0,0 +1,23 @@
using Elsa.Features.Services;
using Elsa.Scheduling.Features;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
/// <summary>
/// Provides extension methods for <see cref="IModule"/> instances.
/// </summary>
public static class ModuleExtensions
{
/// <summary>
/// Enables the scheduling feature.
/// </summary>
/// <param name="module">The module.</param>
/// <param name="configure">A delegate to configure the feature.</param>
/// <returns>The module.</returns>
public static IModule UseScheduling(this IModule module, Action<SchedulingFeature>? configure = null )
{
module.Configure(configure);
return module;
}
}

View file

@ -0,0 +1,45 @@
using Elsa.Common;
using Elsa.Scheduling;
using Elsa.Scheduling.Bookmarks;
using Elsa.Workflows;
using Elsa.Workflows.Models;
// ReSharper disable once CheckNamespace
namespace Elsa.Extensions;
public static class TimerActivityExecutionContextExtensions
{
/// <summary>
/// Repeats the execution of the current activity at the specified interval.
/// </summary>
/// <param name="context">The execution context of the activity.</param>
/// <param name="interval">The time interval after which the activity should be repeated.</param>
/// <param name="callback">An optional callback to execute immediately if the workflow is triggered.</param>
public static void RepeatWithInterval(this ActivityExecutionContext context, TimeSpan interval, ExecuteActivityDelegate? callback = null)
{
if(context.IsTriggerOfWorkflow())
{
callback?.Invoke(context);
return;
}
var clock = context.ExpressionExecutionContext.GetRequiredService<ISystemClock>();
var resumeAt = clock.UtcNow.Add(interval);
var bookmarkOptions = new CreateBookmarkArgs
{
BookmarkName = SchedulingStimulusNames.Timer,
Stimulus = new TimerBookmarkPayload(resumeAt),
Callback = callback
};
context.CreateBookmark(bookmarkOptions);
}
public static TimerTriggerPayload GetTimerTriggerStimulus(this TriggerIndexingContext context, TimeSpan interval)
{
var clock = context.ExpressionExecutionContext.GetRequiredService<ISystemClock>();
var executeAt = clock.UtcNow.Add(interval);
context.TriggerName = SchedulingStimulusNames.Timer;
return new(executeAt, interval);
}
}

View file

@ -0,0 +1,61 @@
using Elsa.Common.Features;
using Elsa.Common.Multitenancy;
using Elsa.Extensions;
using Elsa.Features.Abstractions;
using Elsa.Features.Attributes;
using Elsa.Features.Services;
using Elsa.Scheduling.Bookmarks;
using Elsa.Scheduling.Handlers;
using Elsa.Scheduling.HostedServices;
using Elsa.Scheduling.Services;
using Elsa.Scheduling.TriggerPayloadValidators;
using Elsa.Workflows.Management.Features;
using Microsoft.Extensions.DependencyInjection;
namespace Elsa.Scheduling.Features;
/// <summary>
/// Provides scheduling features to the system.
/// </summary>
[DependsOn(typeof(SystemClockFeature))]
public class SchedulingFeature : FeatureBase
{
/// <inheritdoc />
public SchedulingFeature(IModule module) : base(module)
{
}
/// <summary>
/// Gets or sets the trigger scheduler.
/// </summary>
public Func<IServiceProvider, IWorkflowScheduler> WorkflowScheduler { get; set; } = sp => sp.GetRequiredService<DefaultWorkflowScheduler>();
/// <summary>
/// Gets or sets the CRON parser.
/// </summary>
public Func<IServiceProvider, ICronParser> CronParser { get; set; } = sp => sp.GetRequiredService<CronosCronParser>();
/// <inheritdoc />
public override void Apply()
{
Services
.AddSingleton<UpdateTenantSchedules>()
.AddSingleton<ITenantActivatedEvent>(sp => sp.GetRequiredService<UpdateTenantSchedules>())
.AddSingleton<ITenantDeactivatedEvent>(sp => sp.GetRequiredService<UpdateTenantSchedules>())
.AddSingleton<IScheduler, LocalScheduler>()
.AddSingleton<CronosCronParser>()
.AddSingleton(CronParser)
.AddScoped<ITriggerScheduler, DefaultTriggerScheduler>()
.AddScoped<IBookmarkScheduler, DefaultBookmarkScheduler>()
.AddScoped<DefaultWorkflowScheduler>()
.AddSingleton(CronParser)
.AddScoped(WorkflowScheduler)
.AddBackgroundTask<CreateSchedulesBackgroundTask>()
.AddHandlersFrom<ScheduleWorkflows>()
//Trigger payload validators.
.AddTriggerPaylodValidator<CronTriggerPayloadValidator, CronTriggerPayload>();
Module.Configure<WorkflowManagementFeature>(management => management.AddActivitiesFrom<SchedulingFeature>());
}
}

View file

@ -0,0 +1,40 @@
using Elsa.Mediator.Contracts;
using Elsa.Workflows.Management.Notifications;
using Elsa.Workflows.Runtime;
using Elsa.Workflows.Runtime.Filters;
using Elsa.Workflows.Runtime.Notifications;
namespace Elsa.Scheduling.Handlers;
/// <summary>
/// Deletes scheduled jobs based on deleted workflow triggers and bookmarks.
/// </summary>
public class DeleteSchedules(ITriggerScheduler triggerScheduler, IBookmarkScheduler bookmarkScheduler, ITriggerStore triggerStore, IBookmarkStore bookmarkStore)
:
INotificationHandler<WorkflowDefinitionDeleting>,
INotificationHandler<WorkflowDefinitionsDeleting>,
INotificationHandler<WorkflowDefinitionVersionDeleting>,
INotificationHandler<WorkflowDefinitionVersionsDeleting>,
INotificationHandler<BookmarksDeleting>
{
async Task INotificationHandler<BookmarksDeleting>.HandleAsync(BookmarksDeleting notification, CancellationToken cancellationToken)
{
var ids = notification.Bookmarks.Select(x => x.Id).ToList();
var bookmarks = await bookmarkStore.FindManyAsync(new BookmarkFilter { BookmarkIds = ids }, cancellationToken);
await bookmarkScheduler.UnscheduleAsync(bookmarks, cancellationToken);
}
async Task INotificationHandler<WorkflowDefinitionDeleting>.HandleAsync(WorkflowDefinitionDeleting notification, CancellationToken cancellationToken) => await RemoveSchedulesAsync(new TriggerFilter { WorkflowDefinitionId = notification.DefinitionId }, cancellationToken);
async Task INotificationHandler<WorkflowDefinitionsDeleting>.HandleAsync(WorkflowDefinitionsDeleting notification, CancellationToken cancellationToken) => await RemoveSchedulesAsync(new TriggerFilter { WorkflowDefinitionIds = notification.DefinitionIds }, cancellationToken);
async Task INotificationHandler<WorkflowDefinitionVersionDeleting>.HandleAsync(WorkflowDefinitionVersionDeleting notification, CancellationToken cancellationToken) =>
await RemoveSchedulesAsync(new TriggerFilter { WorkflowDefinitionVersionId = notification.WorkflowDefinition.Id }, cancellationToken);
async Task INotificationHandler<WorkflowDefinitionVersionsDeleting>.HandleAsync(WorkflowDefinitionVersionsDeleting notification, CancellationToken cancellationToken) => await RemoveSchedulesAsync(new TriggerFilter { WorkflowDefinitionVersionIds = notification.Ids }, cancellationToken);
private async Task RemoveSchedulesAsync(TriggerFilter filter, CancellationToken cancellationToken)
{
var triggers = await triggerStore.FindManyAsync(filter, cancellationToken);
await triggerScheduler.UnscheduleAsync(triggers, cancellationToken);
}
}

View file

@ -0,0 +1,29 @@
using Elsa.Mediator.Contracts;
using Elsa.Mediator.Models;
using Elsa.Scheduling.Commands;
namespace Elsa.Scheduling.Handlers;
/// <summary>
/// A command handler for <see cref="RunScheduledTask"/>.
/// </summary>
public class RunScheduledTaskHandler : ICommandHandler<RunScheduledTask>
{
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// Initializes a new instance of the <see cref="RunScheduledTaskHandler"/> class.
/// </summary>
public RunScheduledTaskHandler(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
/// <inheritdoc />
public async Task<Unit> HandleAsync(RunScheduledTask command, CancellationToken cancellationToken)
{
var taskExecutionContext = new TaskExecutionContext(_serviceProvider, cancellationToken);
await command.Task.ExecuteAsync(taskExecutionContext);
return Unit.Instance;
}
}

View file

@ -0,0 +1,41 @@
using Elsa.Mediator.Contracts;
using Elsa.Workflows.Runtime.Notifications;
namespace Elsa.Scheduling.Handlers;
/// <summary>
/// Updates scheduled jobs based on updated workflow triggers and bookmarks.
/// </summary>
public class ScheduleWorkflows : INotificationHandler<WorkflowTriggersIndexed>, INotificationHandler<WorkflowBookmarksIndexed>
{
private readonly ITriggerScheduler _triggerScheduler;
private readonly IBookmarkScheduler _bookmarkScheduler;
/// <summary>
/// Initializes a new instance of the <see cref="ScheduleWorkflows"/> class.
/// </summary>
public ScheduleWorkflows(ITriggerScheduler triggerScheduler, IBookmarkScheduler bookmarkScheduler)
{
_triggerScheduler = triggerScheduler;
_bookmarkScheduler = bookmarkScheduler;
}
/// <summary>
/// Updates scheduled jobs based on updated triggers.
/// </summary>
public async Task HandleAsync(WorkflowTriggersIndexed notification, CancellationToken cancellationToken)
{
await _triggerScheduler.UnscheduleAsync(notification.IndexedWorkflowTriggers.RemovedTriggers, cancellationToken);
await _triggerScheduler.ScheduleAsync(notification.IndexedWorkflowTriggers.AddedTriggers, cancellationToken);
}
/// <summary>
/// Updates scheduled jobs based on updated bookmarks.
/// </summary>
public async Task HandleAsync(WorkflowBookmarksIndexed notification, CancellationToken cancellationToken)
{
var workflowInstanceId = notification.IndexedWorkflowBookmarks.WorkflowExecutionContext.Id;
await _bookmarkScheduler.UnscheduleAsync(notification.IndexedWorkflowBookmarks.RemovedBookmarks, cancellationToken);
await _bookmarkScheduler.ScheduleAsync(workflowInstanceId, notification.IndexedWorkflowBookmarks.AddedBookmarks, cancellationToken);
}
}

View file

@ -0,0 +1,60 @@
using Elsa.Common.Multitenancy;
using Elsa.Scheduling.Activities;
using Elsa.Workflows.Helpers;
using Elsa.Workflows.Runtime;
using Elsa.Workflows.Runtime.Entities;
using Elsa.Workflows.Runtime.Filters;
using Microsoft.Extensions.DependencyInjection;
using Timer = Elsa.Scheduling.Activities.Timer;
namespace Elsa.Scheduling.Handlers;
public class UpdateTenantSchedules : ITenantActivatedEvent, ITenantDeactivatedEvent
{
private static readonly string[] ActivityTypeNames =
[
ActivityTypeNameHelper.GenerateTypeName<Cron>(),
ActivityTypeNameHelper.GenerateTypeName<Timer>(),
ActivityTypeNameHelper.GenerateTypeName<Delay>()
];
public async Task TenantActivatedAsync(TenantActivatedEventArgs args)
{
var serviceProvider = args.TenantScope.ServiceProvider;
var cancellationToken = args.CancellationToken;
var triggerScheduler = args.TenantScope.ServiceProvider.GetRequiredService<ITriggerScheduler>();
var bookmarkScheduler = args.TenantScope.ServiceProvider.GetRequiredService<IBookmarkScheduler>();
var triggers = (await GetTriggersAsync(serviceProvider, cancellationToken)).ToList();
var bookmarks = (await GetBookmarksAsync(serviceProvider, cancellationToken)).ToList();
await triggerScheduler.ScheduleAsync(triggers, args.CancellationToken);
await bookmarkScheduler.ScheduleAsync(bookmarks, args.CancellationToken);
}
public async Task TenantDeactivatedAsync(TenantDeactivatedEventArgs args)
{
var serviceProvider = args.TenantScope.ServiceProvider;
var cancellationToken = args.CancellationToken;
var triggerScheduler = args.TenantScope.ServiceProvider.GetRequiredService<ITriggerScheduler>();
var bookmarkScheduler = args.TenantScope.ServiceProvider.GetRequiredService<IBookmarkScheduler>();
var triggers = (await GetTriggersAsync(serviceProvider, cancellationToken)).ToList();
var bookmarks = (await GetBookmarksAsync(serviceProvider, cancellationToken)).ToList();
await triggerScheduler.UnscheduleAsync(triggers, args.CancellationToken);
await bookmarkScheduler.UnscheduleAsync(bookmarks, args.CancellationToken);
}
private async Task<IEnumerable<StoredTrigger>> GetTriggersAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
var triggerStore = serviceProvider.GetRequiredService<ITriggerStore>();
var filter = TriggerFilter.ByNames(ActivityTypeNames);
return await triggerStore.FindManyAsync(filter, cancellationToken);
}
private async Task<IEnumerable<StoredBookmark>> GetBookmarksAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
var bookmarkStore = serviceProvider.GetRequiredService<IBookmarkStore>();
var filter = BookmarkFilter.ByActivityTypeNames(ActivityTypeNames);
return await bookmarkStore.FindManyAsync(filter, cancellationToken);
}
}

View file

@ -0,0 +1,35 @@
using Elsa.Common;
using Elsa.Workflows.Runtime;
using Elsa.Workflows.Runtime.Filters;
using JetBrains.Annotations;
namespace Elsa.Scheduling.HostedServices;
/// <summary>
/// Creates new schedules when using the default scheduler (which doesn't have its own persistence layer like Quartz or Hangfire).
/// </summary>
[UsedImplicitly]
public class CreateSchedulesBackgroundTask(ITriggerStore triggerStore, IBookmarkStore bookmarkStore, ITriggerScheduler triggerScheduler, IBookmarkScheduler bookmarkScheduler) : BackgroundTask
{
/// <inheritdoc />
public override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var stimulusNames = new[]
{
SchedulingStimulusNames.Cron, SchedulingStimulusNames.Timer, SchedulingStimulusNames.StartAt, SchedulingStimulusNames.Delay,
};
var triggerFilter = new TriggerFilter
{
Names = stimulusNames
};
var bookmarkFilter = new BookmarkFilter
{
Names = stimulusNames
};
var triggers = (await triggerStore.FindManyAsync(triggerFilter, stoppingToken)).ToList();
var bookmarks = (await bookmarkStore.FindManyAsync(bookmarkFilter, stoppingToken)).ToList();
await triggerScheduler.ScheduleAsync(triggers, stoppingToken);
await bookmarkScheduler.ScheduleAsync(bookmarks, stoppingToken);
}
}

View file

@ -0,0 +1,8 @@
namespace Elsa.Scheduling;
/// <summary>
/// The context for scheduling a task.
/// </summary>
/// <param name="ServiceProvider">The service provider.</param>
/// <param name="Task">The task to schedule.</param>
public record ScheduleContext(IServiceProvider ServiceProvider, ITask Task);

Some files were not shown because too many files have changed in this diff Show more