private static ArgumentAnalysisResult AnalyzeArguments( Symbol symbol, AnalyzedArguments arguments, bool isMethodGroupConversion, bool expanded) { Debug.Assert((object)symbol != null); Debug.Assert(arguments != null); ImmutableArray <ParameterSymbol> parameters = symbol.GetParameters(); // The easy out is that we have no named arguments and are in normal form. if (!expanded && arguments.Names.Count == 0) { return(AnalyzeArgumentsForNormalFormNoNamedArguments(parameters, arguments, isMethodGroupConversion, symbol.GetIsVararg())); } // We simulate an additional non-optional parameter for a vararg method. int argumentCount = arguments.Arguments.Count; int[] parametersPositions = null; int? unmatchedArgumentIndex = null; bool? unmatchedArgumentIsNamed = null; // Try to map every argument position to a formal parameter position: for (int argumentPosition = 0; argumentPosition < argumentCount; ++argumentPosition) { // We use -1 as a sentinel to mean that no parameter was found that corresponded to this argument. bool isNamedArgument; int parameterPosition = CorrespondsToAnyParameter(parameters, expanded, arguments, argumentPosition, out isNamedArgument) ?? -1; if (parameterPosition == -1 && unmatchedArgumentIndex == null) { unmatchedArgumentIndex = argumentPosition; unmatchedArgumentIsNamed = isNamedArgument; } if (parameterPosition != argumentPosition && parametersPositions == null) { parametersPositions = new int[argumentCount]; for (int i = 0; i < argumentPosition; ++i) { parametersPositions[i] = i; } } if (parametersPositions != null) { parametersPositions[argumentPosition] = parameterPosition; } } ParameterMap argsToParameters = new ParameterMap(parametersPositions, argumentCount); // We have analyzed every argument and tried to make it correspond to a particular parameter. // There are now three questions we must answer: // // (1) Is there any argument without a corresponding parameter? // (2) was there any named argument that specified a parameter that was already // supplied with a positional parameter? // (3) Is there any non-optional parameter without a corresponding argument? // // If the answer to any of these questions is "yes" then the method is not applicable. // It is possible that the answer to any number of these questions is "yes", and so // we must decide which error condition to prioritize when reporting the error, // should we need to report why a given method is not applicable. We prioritize // them in the given order. // (1) Is there any argument without a corresponding parameter? if (unmatchedArgumentIndex != null) { if (unmatchedArgumentIsNamed.Value) { return(ArgumentAnalysisResult.NoCorrespondingNamedParameter(unmatchedArgumentIndex.Value)); } else { return(ArgumentAnalysisResult.NoCorrespondingParameter(unmatchedArgumentIndex.Value)); } } // (2) was there any named argument that specified a parameter that was already // supplied with a positional parameter? int?nameUsedForPositional = NameUsedForPositional(arguments, argsToParameters); if (nameUsedForPositional != null) { return(ArgumentAnalysisResult.NameUsedForPositional(nameUsedForPositional.Value)); } // (3) Is there any non-optional parameter without a corresponding argument? int?requiredParameterMissing = CheckForMissingRequiredParameter(argsToParameters, parameters, isMethodGroupConversion, expanded); if (requiredParameterMissing != null) { return(ArgumentAnalysisResult.RequiredParameterMissing(requiredParameterMissing.Value)); } // __arglist cannot be used with named arguments (as it doesn't have a name) if (arguments.Names.Count != 0 && symbol.GetIsVararg()) { return(ArgumentAnalysisResult.RequiredParameterMissing(parameters.Length)); } // We're good; this one might be applicable in the given form. return(expanded ? ArgumentAnalysisResult.ExpandedForm(argsToParameters.ToImmutableArray()) : ArgumentAnalysisResult.NormalForm(argsToParameters.ToImmutableArray())); }