RefactorMCP catalog

Create Type

Creates an empty class, interface, record or struct, either in a new file or at the end of an existing one. Composite recipes such as Extract Class and Extract Superclass start with it, so it takes no target, only arguments.

Arguments

ArgumentRequiredMeaning
nameyesThe type's name, with type parameters when generic: Address, Page<T>
fileyesThe file, relative to the solution: created when missing, appended to when present
kindnoclass (the default), interface, record or struct
namespacenoThe namespace to declare the type in
baseTypenoThe base class, or for an interface its base interface. Any kind may name an interface here
{ "refactoring": "create-type", "arguments": { "name": "Address", "file": "Address.cs" } }

Precondition

  • name is an identifier, optionally followed by type parameter names.
  • No type with that name and arity already exists in the namespace.
  • baseType, when given, names a type the project can see, and the kind can derive from it: a class from a class that is neither sealed nor static, a record from a record, and a struct or interface only from interfaces.

Transformation

  • The type is public and empty, with its braces on their own lines.
  • Without namespace, an existing file's type goes in that file's namespace, and a new file's in the namespace most files in the same folder declare, or failing that most files in the project; the global namespace when they declare none.
  • A new file follows the project's namespace style: file-scoped when most of its files use file-scoped namespaces, a block otherwise.
  • In an existing file the type follows the last member of its namespace, separated by a blank line.
  • A new file joins the project whose folder contains it.
  • When baseType only binds with a using directive, the directive is added.

Preserved

  • Every existing file other than the one named, and in that file everything already there, comments and usings included.

Limitations

  • The type is always public, and nested types cannot be created.
  • A base type named by a simple name that matches several accessible types is refused as not found rather than asking which one was meant.

Error codes

CodeMeaning
invalid-namename is not an identifier with optional type parameters
invalid-kindkind is not class, interface, record or struct
type-already-existsthe namespace already has a type of that name and arity
type-not-foundbaseType names no type the project can see
invalid-base-typethe kind of type cannot derive from baseType

Cases

·

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

#base-type-from-another-namespace

Derives the new class from a class in another namespace and imports that namespace

success
Arguments
name"Address"
file"Address.cs"
baseType"Entity"
Address.csadded
1+using Shop.Core;
2+
3+namespace Shop
4+{
5+ public class Address : Entity
6+ {
7+ }
8+}
Core/Entity.csunchanged
11 namespace Shop.Core
22 {
33 public abstract class Entity
44 {
55 public int Id;
66 }
77 }
Customer.csunchanged
11 namespace Shop
22 {
33 public class Customer
44 {
55 }
66 }

#base-type-not-found

Refuses a base type that names no type in the solution

refusal
Arguments
name"Address"
file"Address.cs"
baseType"Location"
Refusestype-not-found mentioning “Location”; every file is left unchanged
Customer.csinput
1 namespace Shop
2 {
3 public class Customer
4 {
5 }
6 }

#class-in-new-file

Creates an empty public class in a new file, in the namespace the project's other files use

success
Arguments
name"Address"
file"Address.cs"
Address.csadded
1+namespace Shop
2+{
3+ public class Address
4+ {
5+ }
6+}
Customer.csunchanged
11 namespace Shop
22 {
33 public class Customer
44 {
55 public string Street;
66 public string City;
77 }
88 }

#generic-class

Creates a generic class when the name carries type parameters

success
Arguments
name"Page<T>"
file"Page.cs"
Page.csadded
1+namespace Shop
2+{
3+ public class Page<T>
4+ {
5+ }
6+}
Catalog.csunchanged
11 namespace Shop
22 {
33 public class Catalog
44 {
55 }
66 }

#in-another-project

Creates the class in the project whose folder holds the file, in that project's namespace

success
Arguments
name"Address"
file"Core/Address.cs"
ProjectsCore; App → Core
Core/Address.csadded
1+namespace Shop.Core
2+{
3+ public class Address
4+ {
5+ }
6+}
App/Program.csunchanged
11 using Shop.Core;
22
33 namespace Shop.App
44 {
55 public static class Program
66 {
77 public static Customer Create() => new Customer();
88 }
99 }
Core/Customer.csunchanged
11 namespace Shop.Core
22 {
33 public class Customer
44 {
55 }
66 }

#interface-in-given-namespace

Creates an interface in a subfolder and a given namespace, following the project's file-scoped namespace style

success
Arguments
name"IPriced"
file"Pricing/IPriced.cs"
kind"interface"
namespace"Shop.Pricing"
Pricing/IPriced.csadded
1+namespace Shop.Pricing;
2+
3+public interface IPriced
4+{
5+}
Order.csunchanged
11 namespace Shop;
22
33 public class Order
44 {
55 public decimal Total;
66 }

#into-existing-file

Adds the class after the last type in an existing file, inside that file's namespace, leaving its comments and usings alone

success
Arguments
name"Address"
file"Customer.cs"
Customer.csmodified
11 using System;
22
33 namespace Shop
44 {
55 // A customer of the shop.
66 public class Customer
77 {
88 public string Name;
99 public DateTime Joined;
1010 }
11+
12+ public class Address
13+ {
14+ }
1115 }

#invalid-kind

Refuses a kind other than class, interface, record or struct

refusal
Arguments
name"Address"
file"Address.cs"
kind"module"
Refusesinvalid-kind; every file is left unchanged
Customer.csinput
1 namespace Shop
2 {
3 public class Customer
4 {
5 }
6 }

#invalid-name

Refuses a name that is not a C# identifier

refusal
Arguments
name"2ndAddress"
file"Address.cs"
Refusesinvalid-name; every file is left unchanged
Customer.csinput
1 namespace Shop
2 {
3 public class Customer
4 {
5 }
6 }

#no-namespace

Creates the class in the global namespace when the project's files declare none

success
Arguments
name"Address"
file"Address.cs"
Address.csadded
1+public class Address
2+{
3+}
Customer.csunchanged
11 public class Customer
22 {
33 }

#record-with-base-type

Creates a record deriving from an existing record

success
Arguments
name"Money"
file"Money.cs"
kind"record"
baseType"Value"
Money.csadded
1+namespace Shop
2+{
3+ public record Money : Value
4+ {
5+ }
6+}
Value.csunchanged
11 namespace Shop
22 {
33 public abstract record Value
44 {
55 }
66 }

#sealed-base-type

Refuses to derive from a sealed class

refusal
Arguments
name"Address"
file"Address.cs"
baseType"Postcode"
Refusesinvalid-base-type; every file is left unchanged
Postcode.csinput
1 namespace Shop
2 {
3 public sealed class Postcode
4 {
5 }
6 }

#struct

Creates a struct

success
Arguments
name"Point"
file"Point.cs"
kind"struct"
Point.csadded
1+namespace Shop
2+{
3+ public struct Point
4+ {
5+ }
6+}
Map.csunchanged
11 namespace Shop
22 {
33 public class Map
44 {
55 }
66 }

#type-already-exists

Refuses when the namespace already has a type of that name

refusal
Arguments
name"Address"
file"Location.cs"
Refusestype-already-exists mentioning “Shop.Address”; every file is left unchanged
Address.csinput
1 namespace Shop
2 {
3 public class Address
4 {
5 }
6 }