/// <summary> /// Initializes a new instance of <see cref="PrecompilationTagHelperTypeResolver"/>. /// </summary> /// <param name="compilation">The <see cref="CodeAnalysis.Compilation"/>.</param> public PrecompilationTagHelperTypeResolver(CodeAnalysis.Compilation compilation) { if (compilation == null) { throw new ArgumentNullException(nameof(compilation)); } _compilation = compilation; }
/// <summary> /// Discovers the available actions of the given machine. /// </summary> /// <param name="machine">The machine.</param> /// <param name="compilation">The compilation.</param> private void DiscoverMachineActions(ClassDeclarationSyntax machine, CodeAnalysis.Compilation compilation) { var model = compilation.GetSemanticModel(machine.SyntaxTree); var onEntryActionNames = machine.DescendantNodes().OfType <ClassDeclarationSyntax>(). Where(val => this.IsState(compilation, val)). SelectMany(val => val.AttributeLists). SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEntry")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 1). Where(val => val.ArgumentList.Arguments[0].Expression is LiteralExpressionSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as LiteralExpressionSyntax). Select(val => val.Token.ValueText). ToList(); var onEntryNameOfActionNames = machine.DescendantNodes().OfType <ClassDeclarationSyntax>(). Where(val => this.IsState(compilation, val)). SelectMany(val => val.AttributeLists). SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEntry")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 1). Where(val => val.ArgumentList.Arguments[0].Expression is InvocationExpressionSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as InvocationExpressionSyntax). Where(val => val.Expression is IdentifierNameSyntax). Where(val => (val.Expression as IdentifierNameSyntax).Identifier.ValueText.Equals("nameof")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 1). Where(val => val.ArgumentList.Arguments[0].Expression is IdentifierNameSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as IdentifierNameSyntax). Select(val => val.Identifier.ValueText). ToList(); var onExitActionNames = machine.DescendantNodes().OfType <ClassDeclarationSyntax>(). Where(val => this.IsState(compilation, val)). SelectMany(val => val.AttributeLists). SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnExit")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 1). Where(val => val.ArgumentList.Arguments[0].Expression is LiteralExpressionSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as LiteralExpressionSyntax). Select(val => val.Token.ValueText). ToList(); var onExitNameOfActionNames = machine.DescendantNodes().OfType <ClassDeclarationSyntax>(). Where(val => this.IsState(compilation, val)). SelectMany(val => val.AttributeLists). SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnExit")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 1). Where(val => val.ArgumentList.Arguments[0].Expression is InvocationExpressionSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as InvocationExpressionSyntax). Where(val => val.Expression is IdentifierNameSyntax). Where(val => (val.Expression as IdentifierNameSyntax).Identifier.ValueText.Equals("nameof")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 1). Where(val => val.ArgumentList.Arguments[0].Expression is IdentifierNameSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as IdentifierNameSyntax). Select(val => val.Identifier.ValueText). ToList(); var onEventDoActionNames = machine.DescendantNodes().OfType <ClassDeclarationSyntax>(). Where(val => this.IsState(compilation, val)). SelectMany(val => val.AttributeLists). SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEventDoAction")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 2). Where(val => val.ArgumentList.Arguments[1].Expression is LiteralExpressionSyntax). Select(val => val.ArgumentList.Arguments[1].Expression as LiteralExpressionSyntax). Select(val => val.Token.ValueText). ToList(); var onEventDoNameOfActionNames = machine.DescendantNodes().OfType <ClassDeclarationSyntax>(). Where(val => this.IsState(compilation, val)). SelectMany(val => val.AttributeLists). SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEventDoAction")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 2). Where(val => val.ArgumentList.Arguments[1].Expression is InvocationExpressionSyntax). Select(val => val.ArgumentList.Arguments[1].Expression as InvocationExpressionSyntax). Where(val => val.Expression is IdentifierNameSyntax). Where(val => (val.Expression as IdentifierNameSyntax).Identifier.ValueText.Equals("nameof")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count == 1). Where(val => val.ArgumentList.Arguments[0].Expression is IdentifierNameSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as IdentifierNameSyntax). Select(val => val.Identifier.ValueText). ToList(); var actionNames = new HashSet <string>(); actionNames.UnionWith(onEntryActionNames); actionNames.UnionWith(onEntryNameOfActionNames); actionNames.UnionWith(onExitActionNames); actionNames.UnionWith(onExitNameOfActionNames); actionNames.UnionWith(onEventDoActionNames); actionNames.UnionWith(onEventDoNameOfActionNames); this.Actions.Add(machine, new List <MethodDeclarationSyntax>()); foreach (var actionName in actionNames) { var action = machine.DescendantNodes().OfType <MethodDeclarationSyntax>(). Where(val => val.ParameterList != null). Where(val => val.ParameterList.Parameters.Count == 0). Where(val => val.Identifier.ValueText.Equals(actionName)). FirstOrDefault(); if (action != null) { this.Actions[machine].Add(action); } } var states = machine.DescendantNodes().OfType <ClassDeclarationSyntax>(). Where(val => this.IsState(compilation, val)). ToList(); var stateMethods = states.SelectMany(val => val.DescendantNodes().OfType <MethodDeclarationSyntax>()). Where(val => val.Modifiers.Any(SyntaxKind.OverrideKeyword)). ToList(); foreach (var method in stateMethods) { this.Actions[machine].Add(method); } }
/// <summary> /// Returns true if the given class declaration is a state. /// </summary> /// <param name="compilation">Compilation</param> /// <param name="classDecl">Class declaration</param> /// <returns>Boolean</returns> protected override bool IsState(CodeAnalysis.Compilation compilation, ClassDeclarationSyntax classDecl) { return(Querying.IsMachineState(compilation, classDecl)); }
/// <summary> /// Returns true if the given class declaration is a machine. /// </summary> /// <param name="compilation">The compilation.</param> /// <param name="classDecl">Class declaration</param> /// <returns>Boolean</returns> protected abstract bool IsMachine(CodeAnalysis.Compilation compilation, ClassDeclarationSyntax classDecl);
/// <summary> /// Returns true if the given class declaration is a stategroup. /// </summary> /// <param name="compilation">The compilation.</param> /// <param name="classDecl">Class declaration</param> /// <returns>Boolean</returns> protected abstract bool IsStateGroup(CodeAnalysis.Compilation compilation, ClassDeclarationSyntax classDecl);
/// <summary> /// Compiles the given compilation to a file. /// </summary> /// <param name="compilation">Compilation</param> /// <param name="outputKind">OutputKind</param> /// <param name="outputPath">OutputPath</param> /// <param name="printResults">Prints the compilation results</param> /// <param name="buildDebugFile">Builds the debug file</param> /// <returns>Output</returns> public string ToFile(CodeAnalysis.Compilation compilation, OutputKind outputKind, string outputPath, bool printResults, bool buildDebugFile) { string assemblyFileName = null; if (outputKind == OutputKind.ConsoleApplication) { assemblyFileName = compilation.AssemblyName + ".exe"; } else if (outputKind == OutputKind.DynamicallyLinkedLibrary) { assemblyFileName = compilation.AssemblyName + ".dll"; } string outputDirectory; if (!this.CompilationContext.Configuration.OutputFilePath.Equals("")) { outputDirectory = this.CompilationContext.Configuration.OutputFilePath; } else { outputDirectory = Path.GetDirectoryName(outputPath); } string fileName = outputDirectory + Path.DirectorySeparatorChar + assemblyFileName; string pdbFileName = outputDirectory + Path.DirectorySeparatorChar + compilation.AssemblyName + ".pdb"; this.OutputDirectoryMap?.Add(compilation.AssemblyName, outputDirectory); this.ProjectAssemblyPathMap?.Add(compilation.AssemblyName, fileName); EmitResult emitResult = null; using (FileStream outputFile = new FileStream(fileName, FileMode.Create, FileAccess.Write), outputPdbFile = new FileStream(pdbFileName, FileMode.Create, FileAccess.Write)) { if (buildDebugFile) { emitResult = compilation.Emit(outputFile, outputPdbFile); } else { emitResult = compilation.Emit(outputFile, null); } } if (emitResult.Success) { if (printResults) { this.Logger.WriteLine("... Writing {0}", fileName); } return(fileName); } this.Logger.WriteLine("---"); this.Logger.WriteLine("Note: the errors below correspond to the intermediate C#-IR, " + "which can be printed using /debug."); this.Logger.WriteLine("---"); var message = string.Join("\r\n", emitResult.Diagnostics); throw new ApplicationException(message); }
/// <summary> /// Checks for special properties. /// </summary> protected override void CheckForSpecialProperties(ClassDeclarationSyntax state, CodeAnalysis.Compilation compilation) { this.CheckForLivenessAttribute(state, compilation); }
async Task <CodeCellEvaluationStatus> CoreEvaluateCodeCellAsync( CodeCellState codeCellState, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken = ClientSession.CancellationToken.LinkWith(cancellationToken); if (!ClientSession.Agent.IsConnected || ClientSession.CompilationWorkspace == null) { codeCellState.View.IsEvaluating = false; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new Diagnostic( DiagnosticSeverity.Error, "Cannot evaluate: not connected to agent.")); return(CodeCellEvaluationStatus.Disconnected); } CodeAnalysis.Compilation compilation = null; IReadOnlyList <Diagnostic> diagnostics = null; ExceptionNode exception = null; bool agentTerminatedWhileEvaluating = false; try { compilation = await ClientSession.CompilationWorkspace.EmitCellCompilationAsync( codeCellState.CodeCellId, new EvaluationEnvironment (ClientSession.WorkingDirectory), cancellationToken); diagnostics = await ClientSession.CompilationWorkspace.GetCellDiagnosticsAsync( codeCellState.CodeCellId, cancellationToken); var integrationAssemblies = compilation .References .Where(ra => ra.HasIntegration) .ToArray(); if (integrationAssemblies.Length > 0) { await ClientSession.Agent.Api.LoadAssembliesAsync( EvaluationContextId, integrationAssemblies); } } catch (Exception e) { exception = ExceptionNode.Create(e); } var hasErrorDiagnostics = codeCellState.View.HasErrorDiagnostics = diagnostics .Any(d => d.Severity == DiagnosticSeverity.Error); foreach (var diagnostic in diagnostics) { codeCellState.View.RenderDiagnostic(diagnostic); } try { if (compilation != null) { codeCellState.IsResultAnExpression = compilation.IsResultAnExpression; await ClientSession.Agent.Api.EvaluateAsync( compilation, cancellationToken); } } catch (XipErrorMessageException e) { exception = e.XipErrorMessage.Exception; } catch (Exception e) { Log.Error(TAG, "marking agent as terminated", e); agentTerminatedWhileEvaluating = true; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new Diagnostic( DiagnosticSeverity.Error, Catalog.GetString( "The application terminated during evaluation of this cell. " + "Run this cell manually to try again."))); } codeCellState.View.IsEvaluating = false; CodeCellEvaluationStatus evaluationStatus; if (exception != null) { codeCellState.View.RenderResult( CultureInfo.CurrentCulture, EvaluationService.FilterException(exception), EvaluationResultHandling.Replace); evaluationStatus = CodeCellEvaluationStatus.EvaluationException; } else if (hasErrorDiagnostics) { return(CodeCellEvaluationStatus.ErrorDiagnostic); } else if (agentTerminatedWhileEvaluating) { evaluationStatus = CodeCellEvaluationStatus.Disconnected; } else { evaluationStatus = CodeCellEvaluationStatus.Success; } if (ClientSession.SessionKind != ClientSessionKind.Workbook) { codeCellState.Freeze(); } codeCellState.NotifyEvaluated(agentTerminatedWhileEvaluating); return(evaluationStatus); }
async Task <CodeCellEvaluationStatus> CoreEvaluateCodeCellAsync( CodeCellState codeCellState, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken = ClientSession.CancellationToken.LinkWith(cancellationToken); if (!ClientSession.Agent.IsConnected || ClientSession.CompilationWorkspace == null) { codeCellState.View.IsEvaluating = false; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new InteractiveDiagnostic( DiagnosticSeverity.Error, "Cannot evaluate: not connected to agent.")); return(CodeCellEvaluationStatus.Disconnected); } CodeAnalysis.Compilation compilation = null; ExceptionNode exception = null; bool agentTerminatedWhileEvaluating = false; try { compilation = await ClientSession.CompilationWorkspace.GetSubmissionCompilationAsync( codeCellState.DocumentId, new EvaluationEnvironment (ClientSession.WorkingDirectory), cancellationToken); var integrationAssemblies = compilation .References .Where(ra => ra.HasIntegration) .ToArray(); if (integrationAssemblies.Length > 0) { await ClientSession.Agent.Api.LoadAssembliesAsync( ClientSession.CompilationWorkspace.EvaluationContextId, integrationAssemblies); } foreach (var dependency in ClientSession.CompilationWorkspace.WebDependencies) { if (ClientSession.AddWebResource(dependency.Location, out var guid)) { await LoadWorkbookDependencyAsync(guid + dependency.Location.Extension); } } } catch (Exception e) { exception = ExceptionNode.Create(e); } var diagnostics = ClientSession.CompilationWorkspace.CurrentSubmissionDiagnostics.Filter(); codeCellState.View.HasErrorDiagnostics = diagnostics.HasErrors; foreach (var diagnostic in diagnostics) { codeCellState.View.RenderDiagnostic((InteractiveDiagnostic)diagnostic); } try { if (compilation != null) { codeCellState.LastEvaluationRequestId = compilation.MessageId; codeCellState.IsResultAnExpression = compilation.IsResultAnExpression; await ClientSession.Agent.Api.EvaluateAsync( compilation, cancellationToken); } } catch (XipErrorMessageException e) { exception = e.XipErrorMessage.Exception; } catch (Exception e) { Log.Error(TAG, "marking agent as terminated", e); agentTerminatedWhileEvaluating = true; codeCellState.View.HasErrorDiagnostics = true; codeCellState.View.RenderDiagnostic(new InteractiveDiagnostic( DiagnosticSeverity.Error, Catalog.GetString( "The application terminated during evaluation of this cell. " + "Run this cell manually to try again."))); } codeCellState.View.IsEvaluating = false; CodeCellEvaluationStatus evaluationStatus; if (exception != null) { codeCellState.View.RenderResult( CultureInfo.CurrentCulture, FilterException(exception), EvaluationResultHandling.Replace); evaluationStatus = CodeCellEvaluationStatus.EvaluationException; } else if (diagnostics.HasErrors) { return(CodeCellEvaluationStatus.ErrorDiagnostic); } else if (agentTerminatedWhileEvaluating) { evaluationStatus = CodeCellEvaluationStatus.Disconnected; } else { evaluationStatus = CodeCellEvaluationStatus.Success; } if (ClientSession.SessionKind != ClientSessionKind.Workbook) { codeCellState.Freeze(); } codeCellState.NotifyEvaluated(agentTerminatedWhileEvaluating); return(evaluationStatus); }
/// <summary> /// Returns true if the given class declaration is a stategroup. /// </summary> protected override bool IsStateGroup(CodeAnalysis.Compilation compilation, ClassDeclarationSyntax classDecl) => Querying.IsMachineStateGroup(compilation, classDecl);
/// <summary> /// Returns true if the given class declaration is a state. /// </summary> protected override bool IsState(CodeAnalysis.Compilation compilation, ClassDeclarationSyntax classDecl) => Querying.IsMonitorState(compilation, classDecl);
/// <summary> /// Checks that a state does not have a duplicate liveness attribute. /// </summary> /// <param name="state">State</param> /// <param name="compilation">Compilation</param> private void CheckForDuplicateLivenessAttributes(ClassDeclarationSyntax state, CodeAnalysis.Compilation compilation) { var model = compilation.GetSemanticModel(state.SyntaxTree); var hotAttributes = state.AttributeLists. SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.Hot")). ToList(); var coldAttributes = state.AttributeLists. SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.Cold")). ToList(); if (hotAttributes.Count > 0 && coldAttributes.Count > 0) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "A monitor state cannot declare both " + "hot and cold liveness attributes.")); } }
/// <summary> /// Checks for special properties. /// </summary> /// <param name="state">State</param> /// <param name="compilation">Compilation</param> protected abstract void CheckForSpecialProperties(ClassDeclarationSyntax state, CodeAnalysis.Compilation compilation);
/// <summary> /// Checks for correct wildcard usage. /// If "defer *" then: /// no other event should be deferred. /// If "ignore *" or "on * do action" then: /// no other action or ignore should be defined. /// If "On * goto" or "On * push" then: /// no other transition, action or ignore should be defined. /// </summary> /// <param name="state">State</param> /// <param name="compilation">Compilation</param> private void CheckForCorrectWildcardUse(ClassDeclarationSyntax state, CodeAnalysis.Compilation compilation) { var model = compilation.GetSemanticModel(state.SyntaxTree); var ignoreTypes = state.AttributeLists. SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.IgnoreEvents")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count > 0). SelectMany(val => val.ArgumentList.Arguments). Where(val => val.Expression is TypeOfExpressionSyntax). Select(val => val.Expression as TypeOfExpressionSyntax); var deferTypes = state.AttributeLists. SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.DeferEvents")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count > 0). SelectMany(val => val.ArgumentList.Arguments). Where(val => val.Expression is TypeOfExpressionSyntax). Select(val => val.Expression as TypeOfExpressionSyntax); var actionTypes = state.AttributeLists. SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEventDoAction")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count > 0). Where(val => val.ArgumentList.Arguments[0].Expression is TypeOfExpressionSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as TypeOfExpressionSyntax); var transitionTypes = state.AttributeLists. SelectMany(val => val.Attributes). Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEventGotoState") || model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEventPushState")). Where(val => val.ArgumentList != null). Where(val => val.ArgumentList.Arguments.Count > 0). Where(val => val.ArgumentList.Arguments[0].Expression is TypeOfExpressionSyntax). Select(val => val.ArgumentList.Arguments[0].Expression as TypeOfExpressionSyntax); var convertToStringSet = new Func <IEnumerable <TypeOfExpressionSyntax>, HashSet <string> >(ls => { var eventHandlers = new HashSet <string>(ls. Where(val => val.Type is IdentifierNameSyntax). Select(val => val.Type as IdentifierNameSyntax). Select(val => val.ToFullString())); eventHandlers.UnionWith(ls. Where(val => val.Type is QualifiedNameSyntax). Select(val => val.Type as QualifiedNameSyntax). Select(val => val.ToFullString())); return(eventHandlers); }); var ignoredEvents = convertToStringSet(ignoreTypes); var deferredEvents = convertToStringSet(deferTypes); var actionEvents = convertToStringSet(actionTypes); var transitionEvents = convertToStringSet(transitionTypes); var isWildCard = new Func <string, bool>(s => s == "WildCardEvent" || s == "Microsoft.PSharp.WildCardEvent"); var hasWildCard = new Func <HashSet <string>, bool>(set => set.Contains("WildCardEvent") || set.Contains("Microsoft.PSharp.WildCardEvent")); if (hasWildCard(deferredEvents)) { foreach (var e in deferredEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot defer other event '" + e + "' when deferring the wildcard event.")); } } if (hasWildCard(ignoredEvents)) { foreach (var e in ignoredEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot ignore other event '" + e + "' when ignoring the wildcard event.")); } foreach (var e in actionEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot define action on '" + e + "' when ignoring the wildcard event.")); } } if (hasWildCard(actionEvents)) { foreach (var e in ignoredEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot ignore other event '" + e + "' when defining an action on the wildcard event.")); } foreach (var e in actionEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot define action on '" + e + "' when defining an action on the wildcard event.")); } } if (hasWildCard(transitionEvents)) { foreach (var e in ignoredEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot ignore other event '" + e + "' when defining a transition on the wildcard event.")); } foreach (var e in actionEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot define action on '" + e + "' when defining a transition on the wildcard event.")); } foreach (var e in transitionEvents.Where(s => !isWildCard(s))) { base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" + state.Identifier.ValueText + "' cannot define a transition on '" + e + "' when defining a transition on the wildcard event.")); } } }