/// <summary> /// Determines whether a method's parameters share lines or are on different lines. /// </summary> /// <param name="arguments">The method arguments.</param> /// <param name="someParametersShareLine">Returns true if some of the parameters are on the same line.</param> /// <param name="someParameterOnDifferentLines">Returns true if some of the parameters are on different lines.</param> private static void DetermineMethodParameterPlacementScheme( IArgumentList arguments, out bool someParametersShareLine, out bool someParameterOnDifferentLines) { Param.AssertNotNull(arguments, "arguments"); someParametersShareLine = false; someParameterOnDifferentLines = false; CodeLocation previousArgumentLocation = null; for (int i = 0; i < arguments.Count; ++i) { CodeLocation argumentLocation = arguments.Location(i); if (i > 0) { if (previousArgumentLocation.StartPoint.LineNumber == argumentLocation.EndPoint.LineNumber) { someParametersShareLine = true; } else { someParameterOnDifferentLines = true; } } previousArgumentLocation = argumentLocation; } }
public override void PopulateValue(object target, IArgumentList args, IDiagnostics diags) { var arg = args.GetLastArg(OptionId); var valueString = arg?.Value ?? attribute.DefaultValue; if (valueString is null) { return; } var converter = TypeDescriptor.GetConverter(Property.PropertyType); if (!converter.CanConvertFrom(typeof(string))) { diags.ReportError( "Type converter for option '{0}' cannot convert from '{1}'.", arg.Option.PrefixedName, typeof(string).Name); return; } object value; try { value = converter.ConvertFromInvariantString(valueString); } catch (NotSupportedException) { diags.ReportError("Invalid value '{1}' in '{0}{1}'", arg.Spelling, valueString); return; } Property.SetValue(target, value); }
/// <summary> /// Checks the placement and formatting of parameters to a method invocation or a method declaration. /// </summary> /// <param name="element"> /// The element. /// </param> /// <param name="parameterListTokens"> /// The tokens that form the parameter list. /// </param> /// <param name="methodArguments"> /// The arguments or parameters to the method. /// </param> /// <param name="methodStartLineNumber"> /// The line number on which the method begins. /// </param> /// <param name="openBracketType"> /// The type of the parameter list opening bracket. /// </param> /// <param name="closeBracketType"> /// The type of the parameter list closing bracket. /// </param> /// <param name="friendlyTypeText"> /// The text to use for violations. /// </param> private void CheckParameters( CsElement element, CsTokenList parameterListTokens, IArgumentList methodArguments, int methodStartLineNumber, CsTokenType openBracketType, CsTokenType closeBracketType, string friendlyTypeText) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterListTokens, "parameterListTokens"); Param.AssertNotNull(methodArguments, "methodArguments"); Param.AssertGreaterThanZero(methodStartLineNumber, "methodStartLineNumber"); Param.Ignore(openBracketType); Param.Ignore(closeBracketType); Node <CsToken> openingBracketNode = this.CheckMethodOpeningBracket(element, parameterListTokens, openBracketType, friendlyTypeText); if (openingBracketNode != null) { this.CheckMethodClosingBracket(element, parameterListTokens, openingBracketNode, closeBracketType, methodArguments); if (methodArguments.Count > 0) { this.CheckMethodArgumentList(element, methodArguments, openingBracketNode, methodStartLineNumber, friendlyTypeText); } } }
/// <summary> /// Checks the placement and formatting of parameters to a method invocation or a method declaration. /// </summary> /// <param name="element">The element.</param> /// <param name="parameterList">The argument list.</param> /// <param name="methodArguments">The arguments or parameters to the method.</param> /// <param name="methodStartLineNumber">The line number on which the method begins.</param> /// <param name="openBracketType">The type of the argument list opening bracket.</param> /// <param name="closeBracketType">The type of the argument list closing bracket.</param> private void CheckParameters( Element element, CodeUnit parameterList, IArgumentList methodArguments, int methodStartLineNumber, TokenType openBracketType, TokenType closeBracketType) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterList, "parameterList"); Param.AssertNotNull(methodArguments, "methodArguments"); Param.AssertGreaterThanZero(methodStartLineNumber, "methodStartLineNumber"); Param.Ignore(openBracketType); Param.Ignore(closeBracketType); OpenBracketToken openingBracket = this.CheckMethodOpeningBracket(element, parameterList, openBracketType); if (openingBracket != null) { this.CheckMethodClosingBracket(element, parameterList, openingBracket, closeBracketType, methodArguments); if (methodArguments.Count > 0) { this.CheckMethodArgumentList(element, parameterList, methodArguments, openingBracket, methodStartLineNumber); } } }
/// <summary> /// use one arg. /// </summary> /// <param name="args"></param> public static void UseOne(this IArgumentList args) { if (args == null) { throw new ArgumentNullException(nameof(args)); } args.Use(1); }
/// <summary> /// Check if all argument are used. /// </summary> /// <param name="args"></param> /// <returns></returns> public static bool IsAllUsed(this IArgumentList args) { if (args == null) { throw new ArgumentNullException(nameof(args)); } return(args.Argv.Count == args.UsedArgvCount); }
public static string[] GetUnusedArguments(this IArgumentList args) { if (args == null) { throw new ArgumentNullException(nameof(args)); } return(args.Argv.Skip(args.UsedArgvCount).ToArray()); }
/// <summary> /// Initializes a new instance of the <see cref="FunctionCallExpression"/> class. /// </summary> /// <param name="identifier">The identifier.</param> /// <param name="argumentList">The argument list.</param> /// <exception cref="System.ArgumentNullException">argumentList or identifier</exception> public FunctionCallExpression(IIdentifier identifier, IArgumentList argumentList) { if (argumentList == null) throw new ArgumentNullException("argumentList"); if (identifier == null) throw new ArgumentNullException("identifier"); this.ArgumentList = argumentList; this.Identifier = identifier; }
public static T UnknownArguments <T>([NotNull] this IArgumentList argv) { if (argv == null) { throw new ArgumentNullException(nameof(argv)); } var args = argv.GetUnusedArguments(); throw new ArgumentsException($"Unknown Arguments: ({string.Join(", ", args)})"); }
public SettingsNotFoundHighlighting( ICSharpArgumentsOwner argumentsOwner, IArgumentList argumentList, string key, string type) { _argumentsOwner = argumentsOwner; _argumentList = argumentList; ToolTip = $"{type} {key} wasn't found in configuration files"; }
public override void PopulateValue(object target, IArgumentList args, IDiagnostics diags) { if (!args.HasArg(OptionId) && !attribute.HasDefaultValue) { return; } bool value = args.GetFlag(OptionId, attribute.DefaultValue); Property.SetValue(target, value); }
public IKaVEList <ISimpleExpression> GetArgumentList(IArgumentList argumentListParam, IList <IStatement> body) { var args = Lists.NewList <ISimpleExpression>(); foreach (var arg in argumentListParam.Arguments) { var argExpr = ToSimpleExpression(arg.Value, body) ?? new UnknownExpression(); args.Add(argExpr); } return(args); }
internal override void PopulateValue( IMemberRef target, int optionId, IArgumentList args) { if (!args.HasArg(optionId)) { return; } var converter = TypeDescriptor.GetConverter(target.ValueType); var value = args.GetLastArgValue(optionId, DefaultValue); target.SetValue(converter.ConvertFromInvariantString(value)); }
public static bool HasBurstProhibitedArguments([NotNull] IArgumentList argumentList) { foreach (var argument in argumentList.Arguments) { var matchingParameterType = argument.MatchingParameter?.Type; if (matchingParameterType != null && !IsBurstPermittedType(matchingParameterType)) { return(true); } } return(false); }
public void ParseSeparate(string prefix, string name, string arg) { OptTable optTable = new OptTableBuilder() .AddSeparate(1, prefix, name) .CreateTable(); var args = new[] { prefix + name, arg }; IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(0, missing.ArgIndex); Assert.Equal(0, missing.ArgCount); Assert.Equal(1, al.Count); Assert.Equal(optTable.MakeArg(1, prefix + name, 0, arg), al[0], argComparer); }
public void ParseSeparateMissingArg() { OptTable optTable = new OptTableBuilder() .AddSeparate(1, "-", "opt") .CreateTable(); var args = new[] { "-opt", "v1", "-opt" }; IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(2, missing.ArgIndex); Assert.Equal(1, missing.ArgCount); Assert.Equal(1, al.Count); Assert.Equal(optTable.MakeArg(1, "-opt", 0, "v1"), al[0], argComparer); }
public void ParseMultiArg(string prefix, string name, string[] extraArgs) { OptTable optTable = new OptTableBuilder() .AddMultiArg(1, prefix, name, extraArgs.Length) .CreateTable(); var args = new[] { prefix + name }.Concat(extraArgs).ToArray(); IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(0, missing.ArgIndex); Assert.Equal(0, missing.ArgCount); Assert.Equal(1, al.Count); Assert.Equal(optTable.MakeArg(1, prefix + name, 0, extraArgs), al[0], argComparer); }
public void ParseRemainingArgs(string prefix, string name) { OptTable optTable = new OptTableBuilder() .AddRemainingArgs(1, prefix, name) .CreateTable(); var args = new[] { prefix + name, prefix + name, "value", "-flag" }; IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(0, missing.ArgIndex); Assert.Equal(0, missing.ArgCount); Assert.Equal(1, al.Count); Assert.Equal(optTable.MakeArg(1, prefix + name, 0, prefix + name, "value", "-flag"), al[0], argComparer); }
public void ParseOption(string prefix, string name, int argCount) { var opt = new StubOption(1, prefix, name); OptTable optTable = new OptTableBuilder() .Add(opt) .CreateTable(); var args = Enumerable.Repeat(prefix + name, argCount).ToList(); IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(new MissingArgs(), missing); Assert.Equal(args.Count, al.Count); Assert.Equal(opt.CreatedArgs, al); }
public Action <ITextControl> FillCurrentParameterWithMock(string shortName, IArgumentList argumentList, IObjectCreationExpression selectedElement, int parameterNumber, ICSharpContextActionDataProvider dataProvider) { var argument = dataProvider.ElementFactory.CreateArgument(ParameterKind.VALUE, dataProvider.ElementFactory.CreateExpression($"{shortName}.Object")); ICSharpArgument arg; var shouldRemoveEndComma = true; if (argumentList.Arguments.Count <= 1) { arg = selectedElement.AddArgumentAfter(argument, null); } else if (parameterNumber != 0) { arg = selectedElement.AddArgumentAfter(argument, argumentList.Arguments[parameterNumber - 1]); } else { arg = selectedElement.AddArgumentBefore(argument, argumentList.Arguments[1]); shouldRemoveEndComma = false; } var argumentRange = arg.GetDocumentRange(); // Remove last comma Hack! return(textControl => { TextRange range; if (shouldRemoveEndComma) { range = new TextRange(argumentRange.EndOffset.Offset, argumentRange.EndOffset.Offset + 1); } else { range = new TextRange(argumentRange.StartOffset.Offset - 2, argumentRange.StartOffset.Offset); } var text = textControl.Document.GetText(range); if (text.Contains(",")) { textControl.Document.DeleteText(range); } }); }
public void ParseJoinedMultiplePrefixes() { OptTable optTable = new OptTableBuilder() .AddJoined(1, new[] { "-", "--", "/" }, "opt=") .CreateTable(); var args = new[] { "--opt=value1", "/opt=value2", "-opt=value3" }; IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(0, missing.ArgIndex); Assert.Equal(0, missing.ArgCount); Assert.Equal(3, al.Count); Assert.Equal(optTable.MakeArg(1, "--opt=", 0, "value1"), al[0], argComparer); Assert.Equal(optTable.MakeArg(1, "/opt=", 1, "value2"), al[1], argComparer); Assert.Equal(optTable.MakeArg(1, "-opt=", 2, "value3"), al[2], argComparer); }
public void ParseFlagMultiplePrefixes() { OptTable optTable = new OptTableBuilder() .AddFlag(1, new[] { "-", "--", "/" }, "opt") .CreateTable(); var args = new[] { "--opt", "/opt", "-opt" }; IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(0, missing.ArgIndex); Assert.Equal(0, missing.ArgCount); Assert.Equal(3, al.Count); Assert.Equal(optTable.MakeArg(1, "--opt", 0), al[0], argComparer); Assert.Equal(optTable.MakeArg(1, "/opt", 1), al[1], argComparer); Assert.Equal(optTable.MakeArg(1, "-opt", 2), al[2], argComparer); }
public void ParseMultiArgMissingArgs( string prefix, string name, int argCount, string[] preArgs, string[] postArgs) { OptTable optTable = new OptTableBuilder() .AddUnknown(1) .AddMultiArg(2, prefix, name, argCount) .CreateTable(); var args = preArgs.Concat(new[] { prefix + name }).Concat(postArgs).ToArray(); IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(preArgs.Length, missing.ArgIndex); Assert.Equal(argCount - postArgs.Length, missing.ArgCount); Assert.Equal(preArgs.Length, al.Count); Assert.True(al.All(a => a.Option.Id == 1)); }
public void ParseMixed() { OptTable optTable = new OptTableBuilder() .AddFlag(1, "-", "a") .AddJoined(2, "-", "a=") .CreateTable(); var args = new[] { "-a=123", "-a" }; IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(0, missing.ArgIndex); Assert.Equal(0, missing.ArgCount); Assert.Equal(2, al.Count); Assert.Equal(optTable.MakeArg(2, "-a=", 0, "123"), al[0], argComparer); Assert.Equal(optTable.MakeArg(1, "-a", 1), al[1], argComparer); }
public static bool TryGetNextArgument(this IArgumentList args, out string value) { if (args == null) { throw new ArgumentNullException(nameof(args)); } if (args.Argv.Count == args.UsedArgvCount) { value = null; return(false); } else { value = args.Argv[args.UsedArgvCount]; return(true); } }
public List <string> Parse(IReadOnlyList <string> arguments) { var optTable = builder.CreateTable(); IArgumentList al = optTable.ParseArgs(arguments, out _); foreach (var arg in al) { if (!actions.TryGetValue(arg.Option.Id, out var tuple)) { continue; } tuple.Item1(arg.Value); } return(al.Matching(UnknownId).Select(a => a.Value).ToList()); }
internal override void PopulateValue(IMemberRef target, int optionId, IArgumentList args) { if (!args.HasArg(optionId)) { return; } var values = args.GetAllArgValues(optionId); if (target.CanWrite) { target.SetValue(ConvertCollection(values, target.ValueType)); } else if (target.CanRead) { throw new NotImplementedException(); } }
public IArgumentList Parse(IReadOnlyList <string> args) { SealOptTable(); IArgumentList al = OptTable.ParseArgs(args, out _); foreach (var info in infos) { var attribute = info.Member.MemberInfo.GetCustomAttribute <OptionAttribute>(); if (attribute == null) { continue; } attribute.PopulateValue(info.Member, info.OptionId, al); } return(al); }
/// <summary> /// Checks the argument list to a method or method invocation to ensure that the arguments are /// positioned correctly. /// </summary> /// <param name="element"> /// The element containing the expression. /// </param> /// <param name="arguments"> /// The arguments to the method. /// </param> /// <param name="openingBracketNode"> /// The opening bracket token. /// </param> /// <param name="methodLineNumber"> /// The line number on which the method begins. /// </param> /// <param name="friendlyTypeText"> /// The text to use for the type in reporting violations. /// </param> private void CheckMethodArgumentList(CsElement element, IArgumentList arguments, Node <CsToken> openingBracketNode, int methodLineNumber, string friendlyTypeText) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(arguments, "arguments"); Param.AssertNotNull(openingBracketNode, "openingBracketNode"); Param.AssertGreaterThanZero(methodLineNumber, "methodLineNumber"); // Determine whether all of the parameters are on the same line as one another. bool someParametersShareLine; bool someParameterOnDifferentLines; DetermineMethodParameterPlacementScheme(arguments, out someParametersShareLine, out someParameterOnDifferentLines); // All parameters must either be on the same line, or each parameter must begin on its own line. if (someParametersShareLine && someParameterOnDifferentLines) { this.AddViolation(element, methodLineNumber, Rules.ParametersMustBeOnSameLineOrSeparateLines, friendlyTypeText); } // Determine whether all of the parameters are on the same line as one another. if (someParameterOnDifferentLines) { this.CheckSplitMethodArgumentList(element, arguments, openingBracketNode, friendlyTypeText); } else if (arguments.Count > 0) { // The first argument must start on the same line as the opening bracket, or // on the line after it. int firstArgumentStartLine = arguments.Location(0).LineNumber; if (firstArgumentStartLine != openingBracketNode.Value.LineNumber && firstArgumentStartLine != openingBracketNode.Value.LineNumber + 1) { int commentLineSpan = MeasureCommentLinesAfter(openingBracketNode); if (firstArgumentStartLine != openingBracketNode.Value.LineNumber + commentLineSpan + 1) { this.AddViolation(element, firstArgumentStartLine, Rules.ParameterListMustFollowDeclaration); } } } }
internal override void PopulateValue( IMemberRef target, int optionId, IArgumentList args) { if (!args.HasArg(optionId)) { return; } bool allowMultiple = typeof(ICollection <string>).IsAssignableFrom(target.ValueType) || typeof(ICollection).IsAssignableFrom(target.ValueType); if (allowMultiple) { target.SetValue(args.GetAllArgValues(optionId)); } else { target.SetValue(args.GetLastArgValue(optionId)); } }
public void ParseJoinedMultiple() { OptTable optTable = new OptTableBuilder() .AddJoined(1, "-", "aaaa") .AddJoined(2, new[] { "-", "--" }, "aaa") .AddJoined(3, "-", "a") .AddJoined(4, "--", "aa") .CreateTable(); var args = new[] { "--aaa1", "--aa2", "-aaaaa", "-a4", "-aaa5" }; IArgumentList al = optTable.ParseArgs(args, out var missing); Assert.Equal(0, missing.ArgIndex); Assert.Equal(0, missing.ArgCount); Assert.Equal(5, al.Count); Assert.Equal(optTable.MakeArg(2, "--aaa", 0, "1"), al[0], argComparer); Assert.Equal(optTable.MakeArg(4, "--aa", 1, "2"), al[1], argComparer); Assert.Equal(optTable.MakeArg(1, "-aaaa", 2, "a"), al[2], argComparer); Assert.Equal(optTable.MakeArg(3, "-a", 3, "4"), al[3], argComparer); Assert.Equal(optTable.MakeArg(2, "-aaa", 4, "5"), al[4], argComparer); }
/// <summary> /// Checks the positioning of method parameters which are split across multiple lines. /// </summary> /// <param name="element">The element.</param> /// <param name="parameterList">The argument list.</param> /// <param name="arguments">The method arguments.</param> /// <param name="openingBracket">The opening bracket token.</param> private void CheckSplitMethodArgumentList(Element element, CodeUnit parameterList, IArgumentList arguments, OpenBracketToken openingBracket) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterList, "parameterList"); Param.AssertNotNull(arguments, "arguments"); Param.AssertNotNull(openingBracket, "openingBracket"); Token previousComma = null; bool commaOnSameLineAsPreviousParameterViolation = false; for (int i = 0; i < arguments.Count; ++i) { CodeLocation location = arguments.Location(i); int argumentStartLine = location.LineNumber; CodeUnit argument = arguments.Argument(i); // Some types of parameters or arguments are not allowed to span across multiple lines. if (location.LineSpan > 1 && !arguments.MaySpanMultipleLines(i)) { this.AddViolation(element, argumentStartLine, Rules.ParameterMustNotSpanMultipleLines); } if (i == 0) { // The first argument must start on the line after the opening bracket if (argumentStartLine != openingBracket.LineNumber + 1) { int commentLineSpan = MeasureCommentLinesAfter(openingBracket); if (argumentStartLine != openingBracket.LineNumber + commentLineSpan + 1) { this.AddViolation(element, argumentStartLine, Rules.SplitParametersMustStartOnLineAfterDeclaration, element.FriendlyTypeText); } } } else { // The argument must begin on the line after the previous comma. Debug.Assert(previousComma != null, "The previous comma should have been set."); if (!commaOnSameLineAsPreviousParameterViolation) { if (argumentStartLine != previousComma.LineNumber + 1) { int commentLineSpan = MeasureCommentLinesAfter(previousComma); if (argumentStartLine != previousComma.LineNumber + commentLineSpan + 1) { this.AddViolation(element, argumentStartLine, Rules.ParameterMustFollowComma); } } } } commaOnSameLineAsPreviousParameterViolation = false; // Find the comma after the token list. if (i < arguments.Count - 1) { Token lastTokenInArgument = argument.FindLastDescendentToken(); if (lastTokenInArgument != null) { for (Token token = lastTokenInArgument.FindNextDescendentTokenOf(parameterList); token != null; token = token.FindNextDescendentTokenOf(parameterList)) { if (token.TokenType == TokenType.Comma) { previousComma = token; // The comma must be on the same line as the previous argument. if (previousComma.LineNumber != location.EndPoint.LineNumber) { int commentLineSpan = MeasureCommentLinesBetween(argument.FindLastChildToken(), previousComma, false); if (previousComma.LineNumber != location.EndPoint.LineNumber + commentLineSpan) { this.AddViolation(element, token.LineNumber, Rules.CommaMustBeOnSameLineAsPreviousParameter); commaOnSameLineAsPreviousParameterViolation = true; } } break; } } } } } }
/// <summary> /// Checks the argument list to a method or method invocation to ensure that the arguments are /// positioned correctly. /// </summary> /// <param name="element">The element containing the expression.</param> /// <param name="parameterList">The element's argument list.</param> /// <param name="arguments">The arguments to the method.</param> /// <param name="openingBracket">The opening bracket token.</param> /// <param name="methodLineNumber">The line number on which the method begins.</param> private void CheckMethodArgumentList(Element element, CodeUnit parameterList, IArgumentList arguments, OpenBracketToken openingBracket, int methodLineNumber) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterList, "parameterList"); Param.AssertNotNull(arguments, "arguments"); Param.AssertNotNull(openingBracket, "openingBracket"); Param.AssertGreaterThanZero(methodLineNumber, "methodLineNumber"); // Determine whether all of the parameters are on the same line as one another. bool someParametersShareLine; bool someParameterOnDifferentLines; DetermineMethodParameterPlacementScheme( arguments, out someParametersShareLine, out someParameterOnDifferentLines); // All parameters must either be on the same line, or each argument must begin on its own line. if (someParametersShareLine && someParameterOnDifferentLines) { this.AddViolation( element, methodLineNumber, Rules.ParametersMustBeOnSameLineOrSeparateLines, element.FriendlyTypeText); } // Determine whether all of the parameters are on the same line as one another. if (someParameterOnDifferentLines) { this.CheckSplitMethodArgumentList(element, parameterList, arguments, openingBracket); } else if (arguments.Count > 0) { // The first argument must start on the same line as the opening bracket, or // on the line after it. int firstArgumentStartLine = arguments.Location(0).LineNumber; if (firstArgumentStartLine != openingBracket.LineNumber && firstArgumentStartLine != openingBracket.LineNumber + 1) { int commentLineSpan = MeasureCommentLinesAfter(openingBracket); if (firstArgumentStartLine != openingBracket.LineNumber + commentLineSpan + 1) { this.AddViolation(element, firstArgumentStartLine, Rules.ParameterListMustFollowDeclaration); } } } }
/// <summary> /// Checks a method or method invocation to ensure that the closing bracket is /// on the same line as the last argument. /// </summary> /// <param name="element">The element containing the expression.</param> /// <param name="parameterList">The argument list.</param> /// <param name="openingBracket">The opening bracket.</param> /// <param name="closingBracketType">The type of the closing bracket.</param> /// <param name="arguments">The arguments to the method.</param> private void CheckMethodClosingBracket( Element element, CodeUnit parameterList, OpenBracketToken openingBracket, TokenType closingBracketType, IArgumentList arguments) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterList, "parameterList"); Param.AssertNotNull(openingBracket, "openingBracket"); Param.Ignore(closingBracketType); Param.AssertNotNull(arguments, "arguments"); // Find the closing bracket. CloseBracketToken closingBracket = null; Token next = parameterList.FindNextSiblingToken(); if (next != null && next.Is(closingBracketType)) { closingBracket = (CloseBracketToken)next; } if (closingBracket != null) { if (arguments.Count == 0) { // The closing bracket must be on the same line as the opening bracket. if (openingBracket.LineNumber != closingBracket.LineNumber) { // If the brackets are not on the same line, determine if this is because there are comments // between the brackets. int commentLineSpan = MeasureCommentLinesBetween(openingBracket, closingBracket, false); if (openingBracket.LineNumber + commentLineSpan != closingBracket.LineNumber) { this.AddViolation(element, closingBracket.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfOpeningParenthesis); } } } else { // The closing bracket must be on the same line as the end of the last method argument. int lastArgumentEndLine = arguments.Location(arguments.Count - 1).EndPoint.LineNumber; if (lastArgumentEndLine != closingBracket.LineNumber) { int commentLineSpan = MeasureCommentLinesBetween(arguments.Argument(arguments.Count - 1).FindLastDescendentToken(), closingBracket, false); if (lastArgumentEndLine + commentLineSpan != closingBracket.LineNumber) { this.AddViolation(element, closingBracket.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfLastParameter); } } } } }
/// <summary> /// Checks a method or method invocation to ensure that the closing bracket is /// on the same line as the last parameter. /// </summary> /// <param name="element"> /// The element containing the expression. /// </param> /// <param name="parameterListTokens"> /// The tokens that form the parameter list. /// </param> /// <param name="openingBracketNode"> /// The opening bracket. /// </param> /// <param name="closingBracketType"> /// The type of the closing bracket. /// </param> /// <param name="arguments"> /// The arguments to the method. /// </param> private void CheckMethodClosingBracket( CsElement element, CsTokenList parameterListTokens, Node<CsToken> openingBracketNode, CsTokenType closingBracketType, IArgumentList arguments) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterListTokens, "parameterListTokens"); Param.AssertNotNull(openingBracketNode, "openingBracket"); Param.Ignore(closingBracketType); Param.AssertNotNull(arguments, "arguments"); // Find the closing bracket. Node<CsToken> closingBracketNode = null; for (Node<CsToken> tokenNode = parameterListTokens.Last; tokenNode != null; tokenNode = tokenNode.Previous) { if (tokenNode.Value.CsTokenType == closingBracketType) { closingBracketNode = tokenNode; break; } } if (closingBracketNode != null) { if (arguments.Count == 0) { // The closing bracket must be on the same line as the opening bracket. if (openingBracketNode.Value.LineNumber != closingBracketNode.Value.LineNumber) { // If the brackets are not on the same line, determine if this is because there are comments // between the brackets. int commentLineSpan = MeasureCommentLinesBetween(openingBracketNode, closingBracketNode, false); if (openingBracketNode.Value.LineNumber + commentLineSpan != closingBracketNode.Value.LineNumber) { this.AddViolation(element, closingBracketNode.Value.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfOpeningParenthesis); } } } else { // The closing bracket must be on the same line as the end of the last method argument. int lastArgumentEndLine = arguments.Location(arguments.Count - 1).EndPoint.LineNumber; if (lastArgumentEndLine != closingBracketNode.Value.LineNumber) { int commentLineSpan = MeasureCommentLinesBetween(arguments.Tokens(arguments.Count - 1).Last, closingBracketNode, false); if (lastArgumentEndLine + commentLineSpan != closingBracketNode.Value.LineNumber) { this.AddViolation(element, closingBracketNode.Value.LineNumber, Rules.ClosingParenthesisMustBeOnLineOfLastParameter); } } } } }
/// <summary> /// Checks the placement and formatting of parameters to a method invocation or a method declaration. /// </summary> /// <param name="element"> /// The element. /// </param> /// <param name="parameterListTokens"> /// The tokens that form the parameter list. /// </param> /// <param name="methodArguments"> /// The arguments or parameters to the method. /// </param> /// <param name="methodStartLineNumber"> /// The line number on which the method begins. /// </param> /// <param name="openBracketType"> /// The type of the parameter list opening bracket. /// </param> /// <param name="closeBracketType"> /// The type of the parameter list closing bracket. /// </param> /// <param name="friendlyTypeText"> /// The text to use for violations. /// </param> private void CheckParameters( CsElement element, CsTokenList parameterListTokens, IArgumentList methodArguments, int methodStartLineNumber, CsTokenType openBracketType, CsTokenType closeBracketType, string friendlyTypeText) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(parameterListTokens, "parameterListTokens"); Param.AssertNotNull(methodArguments, "methodArguments"); Param.AssertGreaterThanZero(methodStartLineNumber, "methodStartLineNumber"); Param.Ignore(openBracketType); Param.Ignore(closeBracketType); Node<CsToken> openingBracketNode = this.CheckMethodOpeningBracket(element, parameterListTokens, openBracketType, friendlyTypeText); if (openingBracketNode != null) { this.CheckMethodClosingBracket(element, parameterListTokens, openingBracketNode, closeBracketType, methodArguments); if (methodArguments.Count > 0) { this.CheckMethodArgumentList(element, methodArguments, openingBracketNode, methodStartLineNumber, friendlyTypeText); } } }
/// <summary> /// Checks the positioning of method parameters which are split across multiple lines. /// </summary> /// <param name="element"> /// The element. /// </param> /// <param name="arguments"> /// The method arguments. /// </param> /// <param name="openingBracketNode"> /// The opening bracket token. /// </param> /// <param name="friendlyTypeText"> /// The friendly type text to use in reporting violations. /// </param> private void CheckSplitMethodArgumentList(CsElement element, IArgumentList arguments, Node<CsToken> openingBracketNode, string friendlyTypeText) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(arguments, "arguments"); Param.AssertNotNull(openingBracketNode, "openingBracketNode"); Node<CsToken> previousComma = null; bool commaOnSameLineAsPreviousParameterViolation = false; for (int i = 0; i < arguments.Count; ++i) { CodeLocation location = arguments.Location(i); int argumentStartLine = location.LineNumber; CsTokenList tokens = arguments.Tokens(i); // Some types of parameters or arguments are not allowed to span across multiple lines. if (location.LineSpan > 1 && !arguments.MaySpanMultipleLines(i)) { this.AddViolation(element, argumentStartLine, Rules.ParameterMustNotSpanMultipleLines); } if (i == 0) { // The first argument must start on the line after the opening bracket if (argumentStartLine != openingBracketNode.Value.LineNumber + 1) { int commentLineSpan = MeasureCommentLinesAfter(openingBracketNode); if (argumentStartLine != openingBracketNode.Value.LineNumber + commentLineSpan + 1) { this.AddViolation(element, argumentStartLine, Rules.SplitParametersMustStartOnLineAfterDeclaration, friendlyTypeText); } } } else { // The parameter must begin on the line after the previous comma. Debug.Assert(previousComma != null, "The previous comma should have been set."); if (!commaOnSameLineAsPreviousParameterViolation) { if (argumentStartLine != previousComma.Value.LineNumber + 1) { int commentLineSpan = MeasureCommentLinesAfter(previousComma); if (argumentStartLine != previousComma.Value.LineNumber + commentLineSpan + 1) { this.AddViolation(element, argumentStartLine, Rules.ParameterMustFollowComma); } } } } commaOnSameLineAsPreviousParameterViolation = false; // Find the comma after the token list. if (i < arguments.Count - 1) { for (Node<CsToken> tokenNode = tokens.Last.Next; tokenNode != null; tokenNode = tokenNode.Next) { if (tokenNode.Value.CsTokenType == CsTokenType.Comma) { previousComma = tokenNode; // The comma must be on the same line as the previous parameter. if (previousComma.Value.LineNumber != location.EndPoint.LineNumber) { int commentLineSpan = MeasureCommentLinesBetween(tokens.Last, previousComma, false); if (previousComma.Value.LineNumber != location.EndPoint.LineNumber + commentLineSpan) { this.AddViolation(element, tokenNode.Value.LineNumber, Rules.CommaMustBeOnSameLineAsPreviousParameter); commaOnSameLineAsPreviousParameterViolation = true; } } break; } } } } }