public CallMethodAction(ParseInfo parseInfo, Scope scope, DeltinScriptParser.MethodContext methodContext, bool usedAsExpression, Scope getter) { this.parseInfo = parseInfo; string methodName = methodContext.PART().GetText(); NameRange = DocRange.GetRange(methodContext.PART()); UsedAsExpression = usedAsExpression; if (methodContext.ASYNC() != null) { if (methodContext.NOT() == null) { Parallel = CallParallel.AlreadyRunning_RestartRule; } else { Parallel = CallParallel.AlreadyRunning_DoNothing; } } var options = scope.GetMethodsByName(methodName); if (options.Length == 0) { parseInfo.Script.Diagnostics.Error($"No method by the name of '{methodName}' exists in the current context.", NameRange); } else { OverloadChooser = new OverloadChooser(options, parseInfo, scope, getter, NameRange, DocRange.GetRange(methodContext), new OverloadError("method '" + methodName + "'")); OverloadChooser.Apply(methodContext.call_parameters()); CallingMethod = (IMethod)OverloadChooser.Overload; ParameterValues = OverloadChooser.Values; if (CallingMethod != null) { CallingMethod.Call(parseInfo, NameRange); // Todo: move this to DefinedFunction.Call. if (CallingMethod is DefinedFunction definedFunction) { definedFunction.OnBlockApply(this); parseInfo.CurrentCallInfo?.Call(definedFunction, NameRange); } if (Parallel != CallParallel.NoParallel && !CallingMethod.Attributes.Parallelable) { parseInfo.Script.Diagnostics.Error($"The method '{CallingMethod.Name}' cannot be called in parallel.", NameRange); } parseInfo.Script.AddHover(DocRange.GetRange(methodContext), CallingMethod.GetLabel(true)); } } }
public CallMethodAction(ParseInfo parseInfo, Scope scope, DeltinScriptParser.MethodContext methodContext, bool usedAsExpression, Scope getter) { this.parseInfo = parseInfo; string methodName = methodContext.PART().GetText(); NameRange = DocRange.GetRange(methodContext.PART()); UsedAsExpression = usedAsExpression; if (methodContext.ASYNC() != null) { if (methodContext.NOT() == null) { Parallel = CallParallel.AlreadyRunning_RestartRule; } else { Parallel = CallParallel.AlreadyRunning_DoNothing; } } // Get all functions with the same name in the current scope. var options = scope.GetMethodsByName(methodName); // If none are found, throw a syntax error. if (options.Length == 0) { parseInfo.Script.Diagnostics.Error($"No method by the name of '{methodName}' exists in the current context.", NameRange); } else { // Make an OverloadChooser to choose an Overload. OverloadChooser = new OverloadChooser(options, parseInfo, scope, getter, NameRange, DocRange.GetRange(methodContext), new OverloadError("method '" + methodName + "'")); // Apply the parameters. OverloadChooser.Apply(methodContext.call_parameters()); // Get the best function. CallingMethod = (IMethod)OverloadChooser.Overload; ParameterValues = OverloadChooser.Values; // CallingMethod may be null if no good functions are found. if (CallingMethod != null) { CallingMethod.Call(parseInfo, NameRange); // If the function's block needs to be applied, check optional restricted calls when 'Applied()' runs. if (CallingMethod is IApplyBlock applyBlock) { applyBlock.OnBlockApply(this); } else // Otherwise, the optional restricted calls can be resolved right away. { // Get optional parameter's restricted calls. OverloadChooser.Match?.CheckOptionalsRestrictedCalls(parseInfo, NameRange); } // Check if the function can be called in parallel. if (Parallel != CallParallel.NoParallel && !CallingMethod.Attributes.Parallelable) { parseInfo.Script.Diagnostics.Error($"The method '{CallingMethod.Name}' cannot be called in parallel.", NameRange); } parseInfo.Script.AddHover(DocRange.GetRange(methodContext), CallingMethod.GetLabel(true)); } } }
/// <summary> /// Dispatch the http context to the router. /// </summary> /// <param name="context">The context to be dispatched.</param> public void DispatchCall(HttpListenerContext context) { var handlerExist = false; var httpMethod = context.Request.HttpMethod.ToLower(); Logger.Write($"Handle request [{httpMethod}]: {context.Request.Url}"); try { var urlInfo = WebApiUrlInfoParser.Parser(_applicationName, context.Request.Url); if (urlInfo != null) { var key = $"{urlInfo.Version}/{urlInfo.HandlerName}"; if (_handlers.ContainsKey(key)) { var matcher = _matchers[httpMethod]; CallingMethod callingMethod = null; if (!string.IsNullOrEmpty(urlInfo.ActionName)) { callingMethod = _handlers[key].GetCallingMethod(urlInfo.ActionName); if (callingMethod != null) { if (!matcher.IsMatch(context, callingMethod)) { callingMethod = null; } } } else { var callingMethods = _handlers[key].GetCallingMethods(); foreach (var method in callingMethods) { if (matcher.IsMatch(context, method)) { callingMethod = method; break; } } } if (callingMethod != null) { if (_parsers.ContainsKey(httpMethod)) { var parser = _parsers[httpMethod]; var args = parser.Parse(context, callingMethod.Parameters.ToArray()); //The parser will add context into the args, so the final count is parameter count + 1. if (args != null && args.Length == callingMethod.Parameters.Count + 1) { handlerExist = true; try { callingMethod.Call(args); } catch (Exception ex) { var argStr = new StringBuilder(); foreach (var arg in args) { argStr.AppendLine($"{arg.Name} = {arg.Value}"); } Logger.Write( $"Call method {callingMethod.Name} with args:{Environment.NewLine + argStr + Environment.NewLine} error :{ex}"); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.Close(); } } } } } } } catch (Exception ex) { Logger.Write($"Handle request error: {ex}"); } if (!handlerExist) { Logger.Write($"Handler for request: {context.Request.Url} not found."); context.Response.StatusCode = (int)HttpStatusCode.NotFound; context.Response.Close(); } }