Beispiel #1
0
        public async Task <ActionExecutionResult> ExecuteActionAsync(ActionStatement actionStatement, IExecuterContext context)
        {
            var metric = new OtterScriptOperationEventMetric(actionStatement.ActionName.FullName);

            try
            {
                var rompContext = ((RompExecutionContext)context.ExternalContext).WithExecuterContext(context);

                var operationType = ExtensionsManager.TryGetOperation(actionStatement.ActionName.Namespace, actionStatement.ActionName.Name);
                if (operationType == null)
                {
                    context.LogScope.Log(LogLevel.Error, $"Unable to resolve operation \"{actionStatement.ActionName}\". A Hedgehog extension may be missing.");
                    return(ExecutionStatus.Fault);
                }

                var operation = (Operation)Activator.CreateInstance(operationType);
                await ScriptPropertyMapper.SetPropertiesAsync(operation, actionStatement, rompContext, context);

                var loggedStatus = ExecutionStatus.Normal;
                var logScopeName = Operation.GetLogScopeName(operationType, actionStatement);
                var scopedLogger = new RompScopedLogger(this, context.LogScope.Current.Push(logScopeName), context.LogScope);
                scopedLogger.BeginScope();

                operation.MessageLogged +=
                    (s, e) =>
                {
                    if (e.Level >= MessageLevel.Warning && loggedStatus < ExecutionStatus.Error)
                    {
                        if (e.Level == MessageLevel.Error)
                        {
                            loggedStatus = ExecutionStatus.Error;
                        }
                        else if (e.Level == MessageLevel.Warning)
                        {
                            loggedStatus = ExecutionStatus.Warning;
                        }
                    }

                    scopedLogger.Log(e.Level, e.Message);
                };

                try
                {
                    var asyncOperation = operation as IExecutingOperation ?? throw new InvalidOperationException();

                    context.SetReportProgressDelegate(() => operation.GetProgress()?.StatementProgress ?? default);
                    await asyncOperation.ExecuteAsync(rompContext).ConfigureAwait(false);

                    ScriptPropertyMapper.ReadOutputs(operation, actionStatement.OutArguments, context);

                    return(loggedStatus);
                }
                catch (ExecutionFailureException ex)
                {
                    if (!string.IsNullOrEmpty(ex.Message))
                    {
                        operation.LogError(ex.Message);
                    }

                    throw new ExecutionFailureException(ex.Message);
                }
                catch (Exception ex)
                {
                    if (ex is OperationCanceledException)
                    {
                        operation.LogError("Operation canceled or timeout expired.");
                        return(ExecutionStatus.Fault);
                    }

                    metric.Error = ex;
                    operation.LogError("Unhandled exception: " + ex.ToString());
                    return(ExecutionStatus.Error);
                }
                finally
                {
                    scopedLogger.EndScope();
                }
            }
            finally
            {
                if (RompConfig.CeipEnabled)
                {
                    EventMetric.Write(metric);
                }
            }
        }
Beispiel #2
0
        private VariableFunction GetVariableFunctionInternal(RuntimeVariableName functionName, IList <RuntimeValue> arguments)
        {
            if (functionName == null)
            {
                throw new ArgumentNullException(nameof(functionName));
            }
            if (arguments == null)
            {
                throw new ArgumentNullException(nameof(arguments));
            }

            var functionType = this.GetFunction(functionName);

            if (functionType == null)
            {
                return(null);
            }

            var function = (VariableFunction)Activator.CreateInstance(functionType.ComponentType);

            var functionParams = (from p in functionType.ComponentType.GetProperties()
                                  let a = p.GetCustomAttribute <VariableFunctionParameterAttribute>()
                                          where a != null
                                          let n = p.GetCustomAttribute <DisplayNameAttribute>()
                                                  orderby a.Index
                                                  select new { Property = p, a.Optional, n?.DisplayName }).ToList();

            int maxParams = Math.Min(functionParams.Count, arguments.Count);

            for (int i = 0; i < maxParams; i++)
            {
                var argValue     = arguments[i];
                var param        = functionParams[i];
                var coercedValue = ScriptPropertyMapper.CoerceValue(argValue, param.Property);
                param.Property.SetValue(function, coercedValue);
            }

            if (maxParams < functionParams.Count)
            {
                var missing = functionParams
                              .Skip(maxParams)
                              .FirstOrDefault(p => !p.Optional);

                if (missing != null)
                {
                    throw new VariableFunctionArgumentMissingException(missing.DisplayName ?? missing.Property.Name);
                }
            }

            var variadicAttr = functionType.ComponentType.GetCustomAttribute <VariadicVariableFunctionAttribute>();

            if (variadicAttr != null)
            {
                var variadicProperty = functionType.ComponentType.GetProperty(variadicAttr.VariadicPropertyName);
                if (variadicProperty != null)
                {
                    var enumerableType = ScriptPropertyMapper.GetEnumerableType(variadicProperty.PropertyType);
                    if (enumerableType != null)
                    {
                        var list = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(enumerableType));
                        foreach (var arg in arguments.Skip(maxParams))
                        {
                            list.Add(ScriptPropertyMapper.CoerceValue(arg, variadicProperty, enumerableType));
                        }

                        variadicProperty.SetValue(function, list);
                    }
                }
            }

            return(function);
        }