RefactorMCP catalog

Rename

Gives a symbol a new name and updates every reference to it across the solution.

Precondition

  • The new name is a C# identifier. A keyword is only accepted escaped with @.
  • The rename leaves the solution compiling: the new name does not clash with a member, local or type already declared where the symbol is.
  • When the symbol is a top-level type whose file is named after it, no file with the new name already exists beside it.

Transformation

  • The declaration and every reference are renamed, in every project that sees the symbol: calls, member accesses, object initializers, named arguments, nameof and <see cref="..."/> in documentation comments.
  • Renaming a virtual or abstract member renames its overrides and base calls; renaming an interface member renames its implicit and explicit implementations. Renaming any of them renames the whole family.
  • Renaming a type renames its constructors. Renaming a generic type renames its constructed uses.
  • Renaming a namespace renames its last part in declarations, using directives and qualified names.
  • A top-level type declared in a file named after it, such as Customer.cs for Customer, has that file renamed to match. A file named after something else keeps its name.
  • A reference the rename would capture, such as a call that an existing overload with the new name would bind to, is kept on the renamed symbol by casting or qualifying it.

Preserved

  • What every reference refers to.
  • Comments, blank lines and layout: only the identifiers change.

Limitations

  • Strings and comments other than documentation references are not searched, so a name written in a string literal or a plain comment keeps the old name.
  • Partial types split across files named Order.cs and Order.Lines.cs have only the file named exactly after the type renamed.

Error codes

CodeMeaning
name-conflictthe new name clashes with existing code, so the result would not compile
invalid-namethe new name is not a C# identifier
file-existsthe type's file would be renamed onto a file that already exists

Cases

·

Diffs show each file from before to after. /*[*/ … /*]*/ marks a selection and /*^*/ a caret; the runner removes them before the refactoring runs.

#across-projects

Renames a public method and its calls in a project that references the declaring one

success
Targetsymbol M:Core.Catalog.Find(System.String)
Arguments
name"Lookup"
ProjectsCore; App → Core
App/Program.csmodified
11 using Core;
22
33 namespace App
44 {
55 public class Program
66 {
7− public string Run(Catalog catalog) => catalog.Find("A1");
7+ public string Run(Catalog catalog) => catalog.Lookup("A1");
88 }
99 }
Core/Catalog.csmodified
11 namespace Core
22 {
33 public class Catalog
44 {
5− public string Find(string sku) => sku;
5+ public string Lookup(string sku) => sku;
66 }
77 }

#conflicting-member-refused

Refuses to give a method the name and signature of another member of its class

refusal
Targetsymbol M:Shop.Cart.Add(System.Int32)
Arguments
name"Remove"
Refusesname-conflict; every file is left unchanged
Cart.csinput
1 namespace Shop
2 {
3 public class Cart
4 {
5 private int _count;
6
7 public void Add(int quantity) => _count += quantity;
8
9 public void Remove(int quantity) => _count -= quantity;
10 }
11 }

#doc-comment-references

Renames a method named in documentation comments and nameof, keeping the comments around it

success
Targetsymbol M:Shop.Order.Total
Arguments
name"GrandTotal"
Order.csmodified
11 namespace Shop
22 {
33 public class Order
44 {
5− /// <summary>The sum of the lines. See also <see cref="Total"/>.</summary>
6− public int Total() => 10; // cached elsewhere
5+ /// <summary>The sum of the lines. See also <see cref="GrandTotal"/>.</summary>
6+ public int GrandTotal() => 10; // cached elsewhere
77
88 // Logged under the method's name.
9− public string Label => nameof(Total);
9+ public string Label => nameof(GrandTotal);
1010 }
1111 }

#file-exists-refused

Refuses to rename a type when the file it would be renamed to already exists

refusal
Targetsymbol T:Shop.Customer
Arguments
name"Client"
Refusesfile-exists; every file is left unchanged
Client.csinput
1 namespace Shop
2 {
3 public class ClientFactory
4 {
5 public Customer Create() => new Customer();
6 }
7 }
Customer.csinput
1 namespace Shop
2 {
3 public class Customer
4 {
5 }
6 }

#generic-type

Renames a generic class and its constructed uses, and renames its file

success
Targetsymbol T:Shop.Box`1
Arguments
name"Container"
Box.csdeleted
1−namespace Shop
2−{
3− public class Box<T>
4− {
5− public Box(T item) => Item = item;
6−
7− public T Item { get; }
8−
9− public Box<T> Copy() => new Box<T>(Item);
10− }
11−}
Container.csadded
1+namespace Shop
2+{
3+ public class Container<T>
4+ {
5+ public Container(T item) => Item = item;
6+
7+ public T Item { get; }
8+
9+ public Container<T> Copy() => new Container<T>(Item);
10+ }
11+}
Shelf.csmodified
11 using System.Collections.Generic;
22
33 namespace Shop
44 {
55 public class Shelf
66 {
7− private readonly List<Box<int>> _boxes = new List<Box<int>>();
7+ private readonly List<Container<int>> _boxes = new List<Container<int>>();
88
9− public void Add(int item) => _boxes.Add(new Box<int>(item));
9+ public void Add(int item) => _boxes.Add(new Container<int>(item));
1010 }
1111 }

#interface-method-and-implementations

Renames an interface method with its implicit and explicit implementations and the calls through each

success
Targetsymbol M:Shop.INotifier.Send(System.String)
Arguments
name"Notify"
INotifier.csmodified
11 namespace Shop
22 {
33 public interface INotifier
44 {
5− void Send(string message);
5+ void Notify(string message);
66 }
77 }
Notifiers.csmodified
11 namespace Shop
22 {
33 public class EmailNotifier : INotifier
44 {
5− public void Send(string message)
5+ public void Notify(string message)
66 {
77 }
88 }
99
1010 public class SmsNotifier : INotifier
1111 {
12− void INotifier.Send(string message)
12+ void INotifier.Notify(string message)
1313 {
1414 }
1515 }
1616
1717 public class Alerts
1818 {
1919 public void Raise(INotifier notifier, EmailNotifier email)
2020 {
21− notifier.Send("down");
22− email.Send("down");
21+ notifier.Notify("down");
22+ email.Notify("down");
2323 }
2424 }
2525 }

#invalid-name-refused

Refuses a new name that is not a C# identifier

refusal
Targetsymbol M:Shop.Order.Total
Arguments
name"class"
Refusesinvalid-name; every file is left unchanged
Order.csinput
1 namespace Shop
2 {
3 public class Order
4 {
5 public int Total() => 10;
6 }
7 }

#local-at-caret

Renames a local variable chosen by caret, and every use of it

success
TargetSample.cs, the /*^*/ caret
Arguments
name"total"
Sample.csmodified
11 public class Sample
22 {
33 public int Sum(int a, int b)
44 {
5− var /*^*/x = a + b;
6− return x * 2;
5+ var total = a + b;
6+ return total * 2;
77 }
88 }

#local-conflict-refused

Refuses to give a local the name of another local in the same scope

refusal
TargetSample.cs, the /*^*/ caret
Arguments
name"total"
Refusesname-conflict; every file is left unchanged
Sample.csinput
1 public class Sample
2 {
3 public int Sum(int a, int b)
4 {
5 var total = a;
6 var /*^*/x = b;
7 return total + x;
8 }
9 }

#method-across-files

Renames one overload of a method and its calls in another file, leaving the other overload alone

success
Targetsymbol M:Shop.Order.Total(System.Int32)
Arguments
name"TotalWithDiscount"
Checkout.csmodified
11 namespace Shop
22 {
33 public class Checkout
44 {
5− public int Pay(Order order) => order.Total(2) + order.Total();
5+ public int Pay(Order order) => order.TotalWithDiscount(2) + order.Total();
66 }
77 }
Order.csmodified
11 namespace Shop
22 {
33 public class Order
44 {
55 public int Total() => 10;
66
7− public int Total(int discount) => Total() - discount;
7+ public int TotalWithDiscount(int discount) => Total() - discount;
88 }
99 }

#namespace

Renames the last part of a namespace in its declaration, using directives and qualified names

success
Targetsymbol N:Shop.Billing
Arguments
name"Payments"
Invoice.csmodified
1−namespace Shop.Billing
1+namespace Shop.Payments
22 {
33 public class Invoice
44 {
55 public decimal Amount { get; set; }
66 }
77 }
Order.csmodified
1−using Shop.Billing;
1+using Shop.Payments;
22
33 namespace Shop
44 {
55 public class Order
66 {
77 public Invoice Bill() => new Invoice();
88
9− public Shop.Billing.Invoice Refund() => new Shop.Billing.Invoice();
9+ public Shop.Payments.Invoice Refund() => new Shop.Payments.Invoice();
1010 }
1111 }

#nullable-property

Renames a nullable property, including its use in an object initializer and a null-conditional access in another file

success
Targetsymbol P:Shop.Customer.Nickname
Arguments
name"DisplayName"
Projectnullable enable
Customer.csmodified
11 namespace Shop
22 {
33 public class Customer
44 {
5− public string? Nickname { get; set; }
5+ public string? DisplayName { get; set; }
66 }
77 }
Greeter.csmodified
11 namespace Shop
22 {
33 public class Greeter
44 {
5− public Customer Create() => new Customer { Nickname = "Ada" };
5+ public Customer Create() => new Customer { DisplayName = "Ada" };
66
7− public int Length(Customer customer) => customer.Nickname?.Length ?? 0;
7+ public int Length(Customer customer) => customer.DisplayName?.Length ?? 0;
88 }
99 }

#overload-kept-by-cast

Gives a method the name of an existing overload, casting an argument where the call would otherwise bind to that overload

success
Targetsymbol M:Shop.Printer.Print(System.Object)
Arguments
name"Show"
Printer.csmodified
11 namespace Shop
22 {
33 public class Printer
44 {
5− public string Print(object value) => "object";
5+ public string Show(object value) => "object";
66
77 public string Show(string value) => "string";
88
9− public string Run() => Print("text");
9+ public string Run() => Show((object)"text");
1010 }
1111 }

#parameter-with-named-arguments

Renames a parameter chosen by caret, its uses in the body and the named arguments that pass it in another file

success
TargetPricing.cs, the /*^*/ caret
Arguments
name"rate"
Checkout.csmodified
11 namespace Shop
22 {
33 public class Checkout
44 {
55 public decimal Total(decimal amount) =>
6− Pricing.Apply(amount, factor: 0.9m) + Pricing.Apply(factor: 2m, amount: amount);
6+ Pricing.Apply(amount, rate: 0.9m) + Pricing.Apply(rate: 2m, amount: amount);
77 }
88 }
Pricing.csmodified
11 namespace Shop
22 {
33 public static class Pricing
44 {
5− public static decimal Apply(decimal amount, decimal /*^*/factor = 1m)
5+ public static decimal Apply(decimal amount, decimal rate = 1m)
66 {
7− return amount * factor;
7+ return amount * rate;
88 }
99 }
1010 }

#type-and-its-file

Renames a class, its constructor and every use of it, and renames the file named after it

success
Targetsymbol T:Shop.Customer
Arguments
name"Client"
Client.csadded
1+namespace Shop
2+{
3+ public class Client
4+ {
5+ public Client(string name)
6+ {
7+ Name = name;
8+ }
9+
10+ public string Name { get; }
11+ }
12+}
Customer.csdeleted
1−namespace Shop
2−{
3− public class Customer
4− {
5− public Customer(string name)
6− {
7− Name = name;
8− }
9−
10− public string Name { get; }
11− }
12−}
Order.csmodified
11 namespace Shop
22 {
33 public class Order
44 {
5− private readonly Customer _customer = new Customer("Ada");
5+ private readonly Client _customer = new Client("Ada");
66
7− public Customer Buyer => _customer;
7+ public Client Buyer => _customer;
88 }
99 }

#type-in-shared-file

Renames a class declared in a file named after something else, leaving the file name alone

success
Targetsymbol T:Shop.Address
Arguments
name"Location"
Models.csmodified
11 namespace Shop
22 {
33 public class Customer
44 {
5− public Address Home { get; set; } = new Address();
5+ public Location Home { get; set; } = new Location();
66 }
77
8− public class Address
8+ public class Location
99 {
1010 public string Street { get; set; } = "";
1111 }
1212 }

#virtual-method-and-overrides

Renames a virtual method together with its override, the base call and the calls through either type

success
Targetsymbol M:Shop.Shape.Area
Arguments
name"Surface"
Report.csmodified
11 namespace Shop
22 {
33 public class Report
44 {
5− public double Sum(Shape shape, Square square) => shape.Area() + square.Area();
5+ public double Sum(Shape shape, Square square) => shape.Surface() + square.Surface();
66 }
77 }
Shapes.csmodified
11 namespace Shop
22 {
33 public class Shape
44 {
5− public virtual double Area() => 0;
5+ public virtual double Surface() => 0;
66 }
77
88 public class Square : Shape
99 {
1010 public double Side { get; set; }
1111
12− public override double Area() => base.Area() + Side * Side;
12+ public override double Surface() => base.Surface() + Side * Side;
1313 }
1414 }