public override IEnumerable<CodeAction> GetActions(RefactoringContext context) { // NOTE: @, multiple occurance var node = context.GetNode(); while (node != null && !IsStringConcatenation(context, node as BinaryOperatorExpression)) node = node.Parent; if (node == null) yield break; var expr = (BinaryOperatorExpression)node; var parent = expr.Parent as BinaryOperatorExpression; while (parent != null && parent.Operator == BinaryOperatorType.Add) { expr = parent; parent = expr.Parent as BinaryOperatorExpression; } yield return new CodeAction(context.TranslateString("Use 'string.Format()'"), script => { var stringType = new PrimitiveType("string"); var formatInvocation = stringType.Invoke("Format"); var formatLiteral = new PrimitiveExpression(""); var counter = 0; var arguments = new List<Expression>(); formatInvocation.Arguments.Add(formatLiteral); var concatItems = GetConcatItems(context, expr); bool hasVerbatimStrings = false; bool hasNonVerbatimStrings = false; foreach (var item in concatItems) { if (IsStringLiteral(item)) { var stringLiteral = (PrimitiveExpression)item; if (stringLiteral.LiteralValue[0] == '@') { hasVerbatimStrings = true; } else { hasNonVerbatimStrings = true; } } } var format = new StringBuilder(); var verbatim = hasVerbatimStrings && hasNonVerbatimStrings; format.Append('"'); foreach (var item in concatItems) { if (IsStringLiteral(item)) { var stringLiteral = (PrimitiveExpression)item; string rawLiteral; if (hasVerbatimStrings && hasNonVerbatimStrings) { rawLiteral = stringLiteral.Value.ToString().Replace("\"", "\"\""); } else { if (stringLiteral.LiteralValue[0] == '@') { verbatim = true; rawLiteral = stringLiteral.LiteralValue.Substring(2, stringLiteral.LiteralValue.Length - 3); } else { rawLiteral = stringLiteral.LiteralValue.Substring(1, stringLiteral.LiteralValue.Length - 2); } } format.Append(QuoteBraces(rawLiteral)); } else { Expression myItem = RemoveUnnecessaryToString(item); string itemFormatStr = DetermineItemFormatString(ref myItem); var index = IndexOf(arguments, myItem); if (index == -1) { // new item formatInvocation.Arguments.Add(myItem.Clone()); arguments.Add(item); format.Append("{" + counter++ + itemFormatStr + "}"); } else { // existing item format.Append("{" + index + itemFormatStr + "}"); } } } format.Append('"'); if (verbatim) format.Insert(0, '@'); formatLiteral.SetValue(format.ToString(), format.ToString()); if (arguments.Count > 0) script.Replace(expr, formatInvocation); else script.Replace(expr, formatLiteral); }, node); }
public override IEnumerable <CodeAction> GetActions(RefactoringContext context) { // NOTE: @, multiple occurance var node = context.GetNode(); while (node != null && !IsStringConcatenation(context, node as BinaryOperatorExpression)) { node = node.Parent; } if (node == null) { yield break; } var expr = (BinaryOperatorExpression)node; var parent = expr.Parent as BinaryOperatorExpression; while (parent != null && parent.Operator == BinaryOperatorType.Add) { expr = parent; parent = expr.Parent as BinaryOperatorExpression; } yield return(new CodeAction(context.TranslateString("Use 'string.Format()'"), script => { var stringType = new PrimitiveType("string"); var formatInvocation = stringType.Invoke("Format"); var formatLiteral = new PrimitiveExpression(""); var counter = 0; var arguments = new List <Expression>(); formatInvocation.Arguments.Add(formatLiteral); var concatItems = GetConcatItems(context, expr); bool hasVerbatimStrings = false; bool hasNonVerbatimStrings = false; foreach (var item in concatItems) { if (IsStringLiteral(item)) { var stringLiteral = (PrimitiveExpression)item; if (stringLiteral.LiteralValue[0] == '@') { hasVerbatimStrings = true; } else { hasNonVerbatimStrings = true; } } } var format = new StringBuilder(); var verbatim = hasVerbatimStrings && hasNonVerbatimStrings; format.Append('"'); foreach (var item in concatItems) { if (IsStringLiteral(item)) { var stringLiteral = (PrimitiveExpression)item; string rawLiteral; if (hasVerbatimStrings && hasNonVerbatimStrings) { rawLiteral = stringLiteral.Value.ToString().Replace("\"", "\"\""); } else { if (stringLiteral.LiteralValue[0] == '@') { verbatim = true; rawLiteral = stringLiteral.LiteralValue.Substring(2, stringLiteral.LiteralValue.Length - 3); } else { rawLiteral = stringLiteral.LiteralValue.Substring(1, stringLiteral.LiteralValue.Length - 2); } } format.Append(QuoteBraces(rawLiteral)); } else { Expression myItem = RemoveUnnecessaryToString(item); string itemFormatStr = DetermineItemFormatString(ref myItem); var index = IndexOf(arguments, myItem); if (index == -1) { // new item formatInvocation.Arguments.Add(myItem.Clone()); arguments.Add(item); format.Append("{" + counter++ + itemFormatStr + "}"); } else { // existing item format.Append("{" + index + itemFormatStr + "}"); } } } format.Append('"'); if (verbatim) { format.Insert(0, '@'); } formatLiteral.SetValue(format.ToString(), format.ToString()); if (arguments.Count > 0) { script.Replace(expr, formatInvocation); } else { script.Replace(expr, formatLiteral); } }, node)); }