diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs index 4cd2c3177b94ced364f8b7bcf3a93666c4b4de94..c95ce78fc58dd9af47980abb373cc810c63e038c 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs @@ -97,22 +97,22 @@ internal static ImmutableArray DeriveArguments(ImmutableArray= boundArguments.Length` when the arguments are specified in parameter order, and no argument is provided at `parameterIndex`. if (argumentIndex == -1 || argumentIndex >= boundArguments.Length) { + // No argument has been supplied for the parameter at `parameterIndex`: + // 1. `argumentIndex == -1' when the arguments are specified out of parameter order, and no argument is provided for parameter corresponding to `parameters[parameterIndex]`. + // 2. `argumentIndex >= boundArguments.Length` when the arguments are specified in parameter order, and no argument is provided at `parameterIndex`. + Symbols.ParameterSymbol parameter = parameters[parameterIndex]; - // Corresponding parameter is optional with default value. if (parameter.HasExplicitDefaultValue) { + // The parameter is optional with a default value. arguments.Add(new Argument(ArgumentKind.DefaultValue, parameter, new Literal(parameter.ExplicitDefaultConstantValue, parameter.Type, null))); } else { - // If corresponding parameter is Param array, then this means 0 element is provided and an Argument of kind == ParamArray will be added, - // otherwise it is an error and null is added. - arguments.Add(DeriveArgument(parameterIndex, argumentIndex, boundArguments, argumentNames, argumentRefKinds, parameters, invocationSyntax)); + // The parameter might be a params array, in which case an empty array will be provided. + arguments.Add(DeriveArgument(parameterIndex, boundArguments.Length, boundArguments, argumentNames, argumentRefKinds, parameters, invocationSyntax)); } } else diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/OperationAnalyzerTests.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/OperationAnalyzerTests.cs index 0ce1c65a827af658e43beda2dbf02017c2d34066..5c7971842ac9795a5249f57a6e4be5b6a6424948 100644 --- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/OperationAnalyzerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/OperationAnalyzerTests.cs @@ -1145,6 +1145,27 @@ public void M1() M0(1, new int[] { 2, 3, 4 }); M0(1, new int[] { 2, 3, 4, 5 }); M0(1, new int[] { 2, 3, 4, 5, 6 }); + M2(1, c: 2); + D d = new D(3, c: 40); + d = new D(""Hello"", 1, 2, 3, 4); + d = new D(""Hello"", new int[] { 1, 2, 3, 4 }); + d = new D(""Hello"", 1, 2, 3); + d = new D(""Hello"", new int[] { 1, 2, 3 }); + } + + public void M2(int a, int b = 10, int c = 20, params int[] d) + { + } + + class D + { + public D(int a, int b = 10, int c = 20, params int[] d) + { + } + + public D(string a, params int[] b) + { + } } } "; @@ -1158,7 +1179,9 @@ public void M1() Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "new int[] { 2, 3, 4, 5 }").WithLocation(16, 15), Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "new int[] { 2, 3, 4, 5 }").WithLocation(16, 15), Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "new int[] { 2, 3, 4, 5, 6 }").WithLocation(17, 15), - Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "new int[] { 2, 3, 4, 5, 6 }").WithLocation(17, 15) + Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "new int[] { 2, 3, 4, 5, 6 }").WithLocation(17, 15), + Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "1").WithLocation(20, 28), + Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "new int[] { 1, 2, 3, 4 }").WithLocation(21, 28) ); } diff --git a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTestAnalyzer.cs b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTestAnalyzer.cs index 0c35e26b6817fefeed78acaf7ae82fa12d05053a..77d771301a5d9356506685649840f9844966eff3 100644 --- a/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTestAnalyzer.cs +++ b/src/Compilers/Core/CodeAnalysisTest/Diagnostics/OperationTestAnalyzer.cs @@ -1070,6 +1070,29 @@ public sealed override void Initialize(AnalysisContext context) } }, OperationKind.InvocationExpression); + + context.RegisterOperationAction( + (operationContext) => + { + IObjectCreationExpression creation = (IObjectCreationExpression)operationContext.Operation; + + foreach (IArgument argument in creation.ArgumentsInParameterOrder) + { + if (argument.Parameter.IsParams) + { + IArrayCreationExpression arrayValue = argument.Value as IArrayCreationExpression; + if (arrayValue != null) + { + Optional dimensionSize = arrayValue.DimensionSizes[0].ConstantValue; + if (dimensionSize.HasValue && IntegralValue(dimensionSize.Value) > 3) + { + operationContext.ReportDiagnostic(Diagnostic.Create(LongParamsDescriptor, argument.Value.Syntax.GetLocation())); + } + } + } + } + }, + OperationKind.ObjectCreationExpression); } private static long IntegralValue(object value) diff --git a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/OperationAnalyzerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/OperationAnalyzerTests.vb index 8c54e661a97af45acf840b1891099e85d07108f3..093a0785a486acda52425eaa1c5eac27692b55df 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/OperationAnalyzerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/OperationAnalyzerTests.vb @@ -1191,6 +1191,15 @@ Class C M0(1, New Integer() { 2, 3, 4 }) M0(1, New Integer() { 2, 3, 4, 5 }) M0(1, New Integer() { 2, 3, 4, 5, 6 }) + Dim local As D = new D(1, 2, 3, 4, 5) + local = new D(1, New Integer() { 2, 3, 4, 5 }) + local = new D(1, 2, 3, 4) + local = new D(1, New Integer() { 2, 3, 4 }) + End Sub +End Class + +Class D + Public Sub New(a As Integer, ParamArray b As Integer()) End Sub End Class ]]> @@ -1207,7 +1216,9 @@ End Class Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "New Integer() { 2, 3, 4, 5 }").WithLocation(12, 15), Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "New Integer() { 2, 3, 4, 5 }").WithLocation(12, 15), Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "New Integer() { 2, 3, 4, 5, 6 }").WithLocation(13, 15), - Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "New Integer() { 2, 3, 4, 5, 6 }").WithLocation(13, 15)) + Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "New Integer() { 2, 3, 4, 5, 6 }").WithLocation(13, 15), + Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "D").WithLocation(14, 30), + Diagnostic(ParamsArrayTestAnalyzer.LongParamsDescriptor.Id, "New Integer() { 2, 3, 4, 5 }").WithLocation(15, 26)) End Sub