private PickyParameter[] ParametersFromContext(DeltinScriptParser.Call_parametersContext context)
        {
            // Return empty if context is null.
            if (context == null)
            {
                return(new PickyParameter[0]);
            }

            // Create the parameters array with the same length as the number of input parameters.
            PickyParameter[] parameters = new PickyParameter[context.call_parameter().Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                PickyParameter parameter = new PickyParameter(false);
                parameters[i] = parameter;

                // Get the picky name.
                // A is not picky, B is picky.
                // 'name' will be null depending on how the parameter is written. A is null, B is not null.
                // A: '5'
                // B: 'parameter: 5'
                parameter.Name  = context.call_parameter(i).PART()?.GetText();
                parameter.Picky = parameter.Name != null;

                if (parameter.Picky)
                {
                    parameter.NameRange = DocRange.GetRange(context.call_parameter(i).PART());                  // Get the name range if picky.
                }
                // If the expression context exists, set expression and expressionRange.
                if (context.call_parameter(i).expr() != null)
                {
                    parameter.Value           = parseInfo.GetExpression(getter, context.call_parameter(i).expr());
                    parameter.ExpressionRange = DocRange.GetRange(context.call_parameter(i).expr());
                }
                else if (parameter.Picky) // TODO: remove condition so only 'else' remains if parameter-quick-skip is not implemented.
                // Throw a syntax error if picky.
                {
                    parseInfo.Script.Diagnostics.Error("Expected expression.", DocRange.GetRange(context.call_parameter(i).TERNARY_ELSE()));
                }

                // Check if there are any duplicate names.
                if (parameter.Picky && parameters.Any(p => p != null && p.Picky && p != parameter && p.Name == parameter.Name))
                {
                    // If there are, syntax error
                    parseInfo.Script.Diagnostics.Error($"The parameter {parameter.Name} was already set.", parameter.NameRange);
                }
            }

            return(parameters);
        }
        private PickyParameter[] ParametersFromContext(List <ParameterValue> context)
        {
            // Return empty if context is null.
            if (context == null)
            {
                return(new PickyParameter[0]);
            }

            // Create the parameters array with the same length as the number of input parameters.
            PickyParameter[] parameters = new PickyParameter[context.Count];
            for (int i = 0; i < parameters.Length; i++)
            {
                PickyParameter parameter = new PickyParameter(false);
                parameters[i] = parameter;

                if (parameter.Picky = context[i].PickyParameter != null)
                {
                    // Get the picky name.
                    parameter.Name = context[i].PickyParameter.Text;
                    // Get the name range
                    parameter.NameRange = context[i].PickyParameter.Range;

                    // Check if there are any duplicate names.
                    if (parameters.Any(p => p != null && p.Picky && p != parameter && p.Name == parameter.Name))
                    {
                        // If there are, syntax error
                        parseInfo.Script.Diagnostics.Error($"The parameter {parameter.Name} was already set.", parameter.NameRange);
                    }
                }

                // Set expression and expressionRange.
                parameter.LambdaInfo      = new ExpectingLambdaInfo();
                parameter.Value           = parseInfo.SetLambdaInfo(parameter.LambdaInfo).GetExpression(getter, context[i].Expression);
                parameter.ExpressionRange = context[i].Expression.Range;
            }

            return(parameters);
        }
        public void SetContext(DeltinScriptParser.Picky_parametersContext context)
        {
            if (_setContext)
            {
                throw new Exception("Already set the context for the overload chooser.");
            }
            PickyContext = context;
            _setContext  = true;

            PickyParameter[] parameters = new PickyParameter[context.picky_parameter().Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                string      name       = context.picky_parameter(i).PART().GetText();
                IExpression expression = null;

                DocRange expressionRange = null;

                // Get the expression. If it doesn't exist, add a syntax error.
                if (context.picky_parameter(i).expr() != null)
                {
                    expression      = DeltinScript.GetExpression(parseInfo, getter, context.picky_parameter(i).expr());
                    expressionRange = DocRange.GetRange(context.picky_parameter(i).expr());
                }
                else
                {
                    parseInfo.Script.Diagnostics.Error("Expected expression.", DocRange.GetRange(context.picky_parameter(i).TERNARY_ELSE()));
                }

                var nameRange = DocRange.GetRange(context.picky_parameter(i).PART());

                // Syntax error if the parameter was already set.
                if (parameters.Any(p => p != null && p.Name == name))
                {
                    parseInfo.Script.Diagnostics.Error($"The parameter {name} was already set.", nameRange);
                }
                else
                {
                    // Add the parameter.
                    parameters[i] = new PickyParameter(
                        name,
                        expression,
                        DocRange.GetRange(context.picky_parameter(i)),
                        nameRange,
                        expressionRange
                        );
                }
            }

            if (!SetParameterCount(parameters.Length))
            {
                return;
            }

            // Match by value types and parameter types.
            foreach (var parameter in parameters)
            {
                foreach (var option in CurrentOptions)
                {
                    int index = -1;
                    for (int i = 0; i < option.Parameters.Length; i++)
                    {
                        if (option.Parameters[i].Name == parameter.Name)
                        {
                            index = i;
                            break;
                        }
                    }

                    if (index == -1)
                    {
                        // Syntax error if the parameter does not exist.
                        optionDiagnostics[option].Add(new Diagnostic(
                                                          string.Format(ErrorMessages.ParameterDoesntExist, parameter.Name),
                                                          parameter.NameRange,
                                                          Diagnostic.Error
                                                          ));
                    }
                    // parameter.Value is null if there is no expression.
                    // A syntax error for this was already thrown earlier.
                    else if (parameter.Value != null)
                    {
                        // Check the types.
                        CompareParameterTypes(parameter.Value, option, index, parameter.ExpressionRange);
                    }
                }
            }
            GetBestOption();

            List <string> pickyParameterCompletion = Overload.Parameters.Select(p => p.Name).ToList();

            ParameterRanges = new DocRange[Overload.Parameters.Length];
            IExpression[] values = new IExpression[Overload.Parameters.Length];
            for (int i = 0; i < values.Length; i++)
            {
                int parameterIndex = -1;
                for (int p = 0; p < parameters.Length && parameterIndex == -1; p++)
                {
                    if (parameters[p].Name == Overload.Parameters[i].Name)
                    {
                        parameterIndex = p;
                        pickyParameterCompletion.Remove(parameters[p].Name);
                    }
                }

                if (parameterIndex != -1)
                {
                    values[i]          = parameters[parameterIndex].Value;
                    ParameterRanges[i] = parameters[parameterIndex].FullRange;
                }
                else
                {
                    values[i] = MissingParameter(Overload.Parameters[i]);
                }
            }
            Values = values;

            // Add the picky parameter completion.
            parseInfo.Script.AddCompletionRange(new CompletionRange(pickyParameterCompletion.Select(p => new CompletionItem()
            {
                Label = p + ":",
                Kind  = CompletionItemKind.Field
            }).ToArray(), CallRange, CompletionRangeKind.Additive));

            GetAdditionalData();
        }