public static MemberAnalysisResult ArgumentParameterMismatch(ArgumentAnalysisResult argAnalysis) { switch (argAnalysis.Kind) { case ArgumentAnalysisResultKind.NoCorrespondingParameter: return(NoCorrespondingParameter(argAnalysis.ArgumentPosition)); case ArgumentAnalysisResultKind.NoCorrespondingNamedParameter: return(NoCorrespondingNamedParameter(argAnalysis.ArgumentPosition)); case ArgumentAnalysisResultKind.DuplicateNamedArgument: return(DuplicateNamedArgument(argAnalysis.ArgumentPosition)); case ArgumentAnalysisResultKind.RequiredParameterMissing: return(RequiredParameterMissing(argAnalysis.ParameterPosition)); case ArgumentAnalysisResultKind.NameUsedForPositional: return(NameUsedForPositional(argAnalysis.ArgumentPosition)); case ArgumentAnalysisResultKind.BadNonTrailingNamedArgument: return(BadNonTrailingNamedArgument(argAnalysis.ArgumentPosition)); default: throw ExceptionUtilities.UnexpectedValue(argAnalysis.Kind); } }
private static ArgumentAnalysisResult AnalyzeArgumentsForNormalFormNoNamedArguments( ImmutableArray <ParameterSymbol> parameters, AnalyzedArguments arguments, bool isMethodGroupConversion, bool isVararg) { Debug.Assert(!parameters.IsDefault); Debug.Assert(arguments != null); Debug.Assert(arguments.Names.Count == 0); // We simulate an additional non-optional parameter for a vararg method. int parameterCount = parameters.Length + (isVararg ? 1 : 0); int argumentCount = arguments.Arguments.Count; // If there are no named arguments then analyzing the argument and parameter // matching in normal form is simple: each argument corresponds exactly to // the matching parameter, and if there are not enough arguments then the // unmatched parameters had better all be optional. If there are too // few parameters then one of the arguments has no matching parameter. // Otherwise, everything is just right. if (argumentCount < parameterCount) { for (int parameterPosition = argumentCount; parameterPosition < parameterCount; ++parameterPosition) { if (parameters.Length == parameterPosition || !CanBeOptional(parameters[parameterPosition], isMethodGroupConversion)) { return(ArgumentAnalysisResult.RequiredParameterMissing(parameterPosition)); } } } else if (parameterCount < argumentCount) { return(ArgumentAnalysisResult.NoCorrespondingParameter(parameterCount)); } // A null map means that every argument in the argument list corresponds exactly to // the same position in the formal parameter list. return(ArgumentAnalysisResult.NormalForm(default(ImmutableArray <int>))); }
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(); bool isVararg = symbol.GetIsVararg(); // 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, isVararg)); } // 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: bool seenNamedParams = false; bool seenOutOfPositionNamedArgument = false; bool isValidParams = IsValidParams(symbol); 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, isValidParams, isVararg, out isNamedArgument, ref seenNamedParams, ref seenOutOfPositionNamedArgument) ?? -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. // We must now answer the following questions: // // (1) Is there any named argument used out-of-position and followed by unnamed arguments? // (2) Is there any argument without a corresponding parameter? // (3) Was there any named argument that specified a parameter that was already // supplied with a positional parameter? // (4) Is there any non-optional parameter without a corresponding argument? // (5) Is there any named argument that were specified twice? // // 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 named argument used out-of-position and followed by unnamed arguments? int?badNonTrailingNamedArgument = CheckForBadNonTrailingNamedArgument(arguments, argsToParameters, parameters); if (badNonTrailingNamedArgument != null) { return(ArgumentAnalysisResult.BadNonTrailingNamedArgument(badNonTrailingNamedArgument.Value)); } // (2) 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)); } } // (3) 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)); } // (4) 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.Any() && arguments.Names.Last() != null && isVararg) { return(ArgumentAnalysisResult.RequiredParameterMissing(parameters.Length)); } // (5) Is there any named argument that were specified twice? int?duplicateNamedArgument = CheckForDuplicateNamedArgument(arguments); if (duplicateNamedArgument != null) { return(ArgumentAnalysisResult.DuplicateNamedArgument(duplicateNamedArgument.Value)); } // We're good; this one might be applicable in the given form. return(expanded ? ArgumentAnalysisResult.ExpandedForm(argsToParameters.ToImmutableArray()) : ArgumentAnalysisResult.NormalForm(argsToParameters.ToImmutableArray())); }