public bool HasParameterErrors => _parameterErrors.Any(p => p != null); // Are there any parameter errors? public OverloadMatch(IOverload option, InstanceAnonymousTypeLinker typeArgLinker, ParseInfo parseInfo, DocRange inferenceErrorRange) { Option = option; _parseInfo = parseInfo; _inferenceErrorRange = inferenceErrorRange; _parameterErrors = new OverloadMatchError[option.Parameters.Length]; if (typeArgLinker != null) { TypeArgLinker = typeArgLinker; TypeArgs = typeArgLinker.TypeArgsFromAnonymousTypes(option.GenericTypes); } else { TypeArgLinker = new InstanceAnonymousTypeLinker(); TypeArgs = new CodeType[option.TypeArgCount]; } }
private OverloadMatch MatchOverload(IOverload option, PickyParameter[] inputParameters, List <ParameterValue> context) { PickyParameter lastPicky = null; // If the generics were provided ('_genericsProvided'), get the type linker from the option. OverloadMatch match = new OverloadMatch(option, _genericsProvided ? option.GetTypeLinker(_generics) : null, _parseInfo, _targetRange); match.OrderedParameters = new PickyParameter[option.Parameters.Length]; // Check type arg count. if (_genericsProvided && _generics.Length != option.TypeArgCount) { match.IncorrectTypeArgCount(_parseInfo.TranslateInfo, _targetRange); } // Iterate through the option's parameters. for (int i = 0; i < inputParameters.Length; i++) { // Out of range if (i >= option.Parameters.Length) { if (i == option.Parameters.Length) { match.Error(string.Format(_errorMessages.BadParameterCount, inputParameters.Length), _targetRange); } continue; } // Non-picky else if (inputParameters[i].ParameterOrdered(option.Parameters[i])) { // If the picky parameters end but there is an additional picky parameter, throw a syntax error. if (lastPicky != null && inputParameters[i].Name == null) { match.Error($"Named argument '{lastPicky.Name}' is used out-of-position but is followed by an unnamed argument", lastPicky.NameRange); } else { match.OrderedParameters[i] = inputParameters[i]; // If _genericsFilled is false, get context-inferred type arguments. if (!_genericsProvided) { ExtractInferredGenerics(match, option.Parameters[i].GetCodeType(_parseInfo.TranslateInfo), inputParameters[i].Value.Type()); } // Next contextual parameter if (i == inputParameters.Length - 1 && i < option.Parameters.Length - 1) { match.LastContextualParameterIndex = i + 1; } } } else // Picky { // Picky parameter ends. lastPicky = inputParameters[i]; // Set relevant picky parameter. bool nameFound = false; for (int p = 0; p < option.Parameters.Length && !nameFound; p++) { if (inputParameters[i].Name == option.Parameters[p].Name) { // A matching parameter was found. match.OrderedParameters[p] = inputParameters[i]; nameFound = true; // If _genericsFilled is false, get context-inferred type arguments. if (!_genericsProvided) { ExtractInferredGenerics(match, option.Parameters[p].GetCodeType(_parseInfo.TranslateInfo), inputParameters[i].Value.Type()); } } } // If the named argument's name is not found, throw an error. if (!nameFound) { match.Error($"Named argument '{lastPicky.Name}' does not exist in the function '{option.GetLabel(_parseInfo.TranslateInfo, LabelInfo.OverloadError)}'.", inputParameters[i].NameRange); } } } // Compare parameter types. match.UpdateAllParameters(); // Make sure every type arg was accounted for. if (!_genericsProvided && !match.TypeArgLinkerCompleted) { match.InferSuccessful = false; } // Get the missing parameters. match.GetMissingParameters(_errorMessages, context, _targetRange, CallRange); return(match); }