public IInvokeResult Invoke(InvokeData invokeInfo)
        {
            var         parseInfo = invokeInfo.ParseInfo;
            MethodGroup group     = ((CallMethodGroup)invokeInfo.Target).Group;

            // Make an OverloadChooser to choose an Overload.
            var overloadChooser = new OverloadChooser(group.Functions.ToArray(), parseInfo, invokeInfo.Scope, invokeInfo.Getter, invokeInfo.TargetRange, invokeInfo.CallRange, new OverloadError("method '" + group.Name + "'"));

            // Apply the parameters.
            overloadChooser.Apply(invokeInfo.Context.Parameters);

            // Get the best function.
            var callingMethod = (IMethod)overloadChooser.Overload;
            var result        = new FunctionInvokeResult(parseInfo, invokeInfo.TargetRange, invokeInfo.UsedAsExpression, callingMethod, overloadChooser.Values, overloadChooser.AdditionalParameterData, overloadChooser.Match);

            // CallingMethod may be null if no good functions are found.
            if (callingMethod != null)
            {
                callingMethod.Call(parseInfo, invokeInfo.TargetRange);

                // If the function's block needs to be applied, check optional restricted calls when 'Applied()' runs.
                if (callingMethod is IApplyBlock applyBlock)
                {
                    applyBlock.OnBlockApply(result);
                }
                else // Otherwise, the optional restricted calls can be resolved right away.
                {
                    // Get optional parameter's restricted calls.
                    overloadChooser.Match?.CheckOptionalsRestrictedCalls(parseInfo, invokeInfo.TargetRange);
                }

                // Check if the function can be called in parallel.
                if (parseInfo.AsyncInfo != null)
                {
                    if (!callingMethod.Attributes.Parallelable)
                    {
                        parseInfo.AsyncInfo.Reject($"The method '{callingMethod.Name}' cannot be called in parallel");
                    }
                    else
                    {
                        parseInfo.AsyncInfo.Accept();
                    }
                }

                parseInfo.Script.AddHover(invokeInfo.Context.Range, callingMethod.GetLabel(true));
            }

            return(result);
        }
Ejemplo n.º 2
0
        public IInvokeResult Invoke(InvokeData invokeInfo)
        {
            var parseInfo = invokeInfo.ParseInfo;

            if (invokeInfo.Target is CallMethodGroup == false)
            {
                parseInfo.Script.Diagnostics.Error("Method name expected", invokeInfo.TargetRange);
                CallMethodAction.DiscardParameters(parseInfo, invokeInfo.Getter, invokeInfo.Context.Parameters);
                return(null);
            }

            var groupCall = (CallMethodGroup)invokeInfo.Target;
            var group     = groupCall.Group;

            // Make an OverloadChooser to choose an Overload.
            var overloadChooser = new OverloadChooser(
                group.Functions.Select(f => new MethodOverload(f)).ToArray(),
                parseInfo,
                invokeInfo.Scope,
                invokeInfo.Getter,
                invokeInfo.TargetRange,
                invokeInfo.CallRange,
                invokeInfo.FullRange,
                new OverloadError("method '" + group.Name + "'")
                );

            // Apply the parameters.
            overloadChooser.Apply(invokeInfo.Context.Parameters, groupCall.TypeArgs.Length > 0, groupCall.TypeArgs);

            // Get the best function.
            var callingMethod = (IMethod)overloadChooser.Overload;
            var result        = new FunctionInvokeResult(parseInfo, invokeInfo.TargetRange, invokeInfo.UsedAsExpression, callingMethod, overloadChooser.AdditionalData, overloadChooser.ParameterResults, overloadChooser.Match);
            var typeArgLinker = overloadChooser.Match?.TypeArgLinker;

            // CallingMethod may be null if no good functions are found.
            if (callingMethod != null)
            {
                result.ReturnType = callingMethod.CodeType?.GetCodeType(parseInfo.TranslateInfo).GetRealType(typeArgLinker);

                // Do not track if any of the generics are null.
                if (overloadChooser.Match.TypeArgs.All(t => t != null))
                {
                    // Track the generics used in the function.
                    parseInfo.Script.Elements.AddTypeArgCall(new TypeArgCall(callingMethod.MethodInfo.Tracker, overloadChooser.Match.TypeArgs));
                }

                if (callingMethod.Attributes.CallInfo != null)
                {
                    // Restricted calls.
                    RestrictedCall.BridgeMethodCall(parseInfo, callingMethod.Attributes.CallInfo, invokeInfo.TargetRange, callingMethod.Name, overloadChooser.Match.Option.RestrictedValuesAreFatal);

                    // Apply
                    callingMethod.Attributes.CallInfo.OnCompleted.OnReady(result.Apply);
                }
                else
                {
                    result.Apply();
                }

                // Check if the function can be called in parallel.
                if (parseInfo.AsyncInfo != null)
                {
                    if (!callingMethod.Attributes.Parallelable)
                    {
                        parseInfo.AsyncInfo.Reject($"The method '{callingMethod.Name}' cannot be called in parallel");
                    }
                    else
                    {
                        parseInfo.AsyncInfo.Accept();
                    }
                }

                // Add the function hover.
                parseInfo.Script.AddHover(invokeInfo.Context.Range, callingMethod.GetLabel(parseInfo.TranslateInfo, new LabelInfo()
                {
                    IncludeDocumentation  = true,
                    IncludeParameterNames = true,
                    IncludeParameterTypes = true,
                    IncludeReturnType     = true,
                    AnonymousLabelInfo    = new AnonymousLabelInfo(typeArgLinker)
                }));
            }

            return(result);
        }