---
uid: application-development.code-weaving-and-generation.about-code-management-csharp
description: "Reference for controlling C# code management in Intent Architect using RoslynWeaver attributes such as IntentManaged, IntentIgnore, and DefaultIntentManaged."
---
# C# Code Management

This article explains how to control [Code Management](https://docs.intentarchitect.com/docs-md/application-development/code-management/about-code-management/about-code-management.md) (Code Weaving) behaviour for C# files when "RoslynWeaver" (the C# code management extension of the `Intent.OutputManager.RoslynWeaver` Module) is used.

## Overview of how it works

The RoslynWeaver parses C# files into an [abstract syntax tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) and applies code management logic on a node-by-node basis. An individual node on the _abstract syntax tree_ is referred to as a _syntax node_. _Syntax nodes_ may have one or more children which are also _syntax nodes_.

![Example of an abstract syntax tree of a C# file](images/syntax-tree-example.png)

_Example of an abstract syntax tree of a C# file._

The RoslynWeaver compares the generated content from the template with the existing file (if there is one) on a node-by-node basis. Instructions in the form of C# attributes are used by the RoslynWeaver for it to determine for a particular _syntax node_ what content it should ignore, replace with content generated by the template or perhaps remove entirely.

## Code management instructions

Instructing the RoslynWeaver on how to treat particular _syntax nodes_ is done using code management instructions in your source code, such as e.g. `[IntentManaged(Mode.Ignore)]`, `[IntentIgnore]`.

### Management modes

Both the `[IntentManaged(…)]` and `[DefaultIntentManaged(…)]` attributes have a mandatory parameter which accepts a `Mode` enum value of one of the following:

| Enum Value | Description |
|------------|-------------|
| `Fully`    | Intent has **full** control over the particular _syntax node_, any deviations in the existing file's _syntax node_ are overwritten with the content generated by the template. Descendant _syntax nodes_ can be opted-out of being fully managed having an `[IntentManaged(…)]` attribute applied to them. |
| `Merge`    | Intent will add and remove Intent generated code for the _the syntax node_ but will never remove code which was manually added¹. |
| `Ignore`   | Intent must **ignore** this _syntax node_ and not remove or overwrite it with content generated by the template. Code management instructions on descendant _syntax nodes_ are likewise ignored, i.e. it is not possible to opt-out of being ignored as a descendant. |

[1] Prior to version 4.7.0 of the `Intent.OutputManager.RoslynWeaver` module, it was not possible for it to identify what was previously generated by Intent so it would never delete anything when in merge mode.

### The `[DefaultIntentManaged(…)]` attribute

The `[DefaultIntentManaged(…)]` attribute can be used to set the "default" (or "fallback") management mode for _syntax nodes_ which otherwise have no code management instructions of their own.

A `[DefaultIntentManaged(<mode>)]` assembly attribute without additional options must be specified at least once at the top of the file and can also be applied any additional number of times with any combination of additional options either as assembly attributes at the top of the file or to _type declaration syntax nodes_ (classes, enums, interfaces, etc), for example:

```csharp
[assembly: DefaultIntentManaged(Mode.Fully)]
[assembly: DefaultIntentManaged(Mode.Fully, Targets = Targets.Usings)]

[DefaultIntentManaged(Mode.Fully, Body = Mode.Ignore, Targets = Targets.Constructors | Targets.Methods)]
public class Class
{
}
```

#### DefaultIntentManaged `Targets` property

The `[DefaultIntentManaged(…)]` attribute's `Targets` property can be set to have a value of one or more `Targets` enum flags to specify that the instruction should only "target" particular _syntax node_ types. To specify multiple target _syntax node_ types, use the [bitwise logical OR operator `|`](https://learn.microsoft.com/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators#logical-or-operator-), e.g. `Targets = Targets.Constructors | Targets.Methods` will make the instruction apply to both _Constructors_ and _Methods_.

The following `Targets` are available:

- `Classes`
- `Constructors`
- `Delegates`
- `EnumMembers`
- `Enums`
- `Fields`
- `Interfaces`
- `Methods`
- `Namespaces`
- `OperatorConversions`
- `Operators`
- `Properties`
- `Records`
- `Structs`
- `TopLevelStatements`
- `Usings`

### The `[IntentManaged(…)]` attribute

_Type declaration syntax nodes_ (e.g. classes, enums, interfaces, etc) and _type member declaration syntax nodes_ (e.g. fields, methods, properties, etc) can have an `[IntentManaged(…)]` attribute applied to them to control their code management behaviour.

#### `[IntentManaged(…)]` when applied to type **member** declaration syntax nodes

The `[IntentManaged(…)]` attribute can be applied to _type member declaration syntax nodes_ (e.g. fields, methods, properties, etc) to control the behaviour of that member in particular, for example to have the code management ignore a method which you made manual changes to, you can add an `[IntentManaged(Mode.Ignore)]` attribute to it like so:

```csharp
[IntentManaged(Mode.Ignore)]
public void ChangeCountry(string country)
{
    throw new NotImplementedException();
}
```

When the RoslynWeaver sees this, it will know not to modify (or remove) this method in any way during code merging.

#### `[IntentManaged(…)]` when applied to **type** declaration syntax nodes

The `[IntentManaged(…)]` attribute can be applied to _type declaration syntax nodes_ (e.g. classes, enums, interfaces, etc) to control the following:

- **Signature:** Controls access modifiers, generic type parameters and what is being derived from and/or implemented.
- **Body:** Controls whether or not members (e.g. fields, methods, properties, etc) of the class should be added/removed (it does not control the _content_ of the members):
  - **Fully:** Members are added to/removed from the existing file to ensure they match the template output.
  - **Merge:** Any members from the template output which are missing from the existing file will be added, additional members which were previously added by Intent will be removed¹ and any additional members which where manually user added will not be removed.
  - **Ignore:** No members will be added to or removed from the existing file.
- **Comments:** Controls comments of the _type declaration_, falls back to `Signature` behaviour if unspecified.
- **Attributes:** Controls attributes of the _type declaration_, falls back to `Signature` behaviour if unspecified.

When a _type declaration syntax node_ has `[IntentManaged(Mode.Ignored)]` applied to it, descendant nodes (i.e. members, such as fields, properties, etc.) all become ignored and will stop being updated or removed. Additionally, code management instructions on descendant nodes are also ignored and disregarded meaning it is not possible to "opt-out" of being ignored as a descendant.

¹ Prior to version 4.7.0 of the `Intent.OutputManager.RoslynWeaver` module, it was not possible for it to identify what was previously generated by Intent so it would never delete anything when in merge mode.

### The `[IntentInitialGen]` attribute

This instruction is useful for having a syntax node which can be initially generated by a template, and then changed or even removed by users without the Software Factory trying to update or put the it back into the file.

When `[IntentInitialGen]` is on a syntax node in a template, it is generated during the initial generation (creation) of a file and is then essentially treated as "Ignored" on subsequent generations. Furthermore, if the syntax node is deleted then it won't be re-generated on subsequent updates to the file.

During initial generation of a file, the instruction is removed from syntax node so this instruction will never be visible except to template authors.

### Code management attribute properties

The `[IntentManaged(…)]` and `[DefaultIntentManaged(…)]` attributes have additional properties which can provide finer grained control of code management for a particular _syntax node_. By default each of these properties has the same `Mode` as the default parameter of the attribute, so:

```csharp
[IntentManaged(Mode.Fully, Body = Mode.Fully, Signature = Mode.Fully, Comments = Mode.Fully, Attributes = Mode.Fully)]
```

is equivalent to:

```csharp
[IntentManaged(Mode.Fully)]
```

The following table documents the available attribute properties and how the RoslynWeaver interprets them when applied to different _syntax node_ types:

| _Syntax node_ type  | Attribute property | Description                                                                                                                                                              |
|---------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| (All)               | Attributes         | By default the `Signature` parameter determines this parameter's setting but this parameter instructs the RoslynWeaver to treat the _syntax node_'s Attribute differently. |
| (All)               | Comments           | By default the `Signature` parameter determines this parameter's setting but this parameter instructs the RoslynWeaver to treat the _syntax node_'s Comments differently.  |
| Class               | Signature          | Instructs the RoslynWeaver to treat the definition of a Class (class name, inheritance, etc.) differently to the default parameter setting.                              |
| Class               | Body               | Instructs the RoslynWeaver to treat the members of a Class (methods, properties, etc.) differently to the default parameter setting.                                     |
| Constructor, Method | Signature          | Instructs the RoslynWeaver to treat the definition of a Method (method name, parameters, return type, etc.) differently to the default parameter setting.                |
| Constructor, Method | Body               | Instructs the RoslynWeaver to treat the implementation part of a method (where the code goes) differently to the default parameter setting.                              |
| Field, Property     | Signature          | Instructs the RoslynWeaver to treat the definition of a Field (field name, type, etc.) differently to the default parameter setting.                                     |
| Field, Property     | Body               | Instructs the RoslynWeaver to treat the value differently to the default parameter setting.                                                                              |

### Shorthand attributes

> [!NOTE]
> Shorthand attributes were introduced in version `4.2.0` of the `Intent.OutputManager.RoslynWeaver` module, ensure you have at least this version of the module installed for them to be able to work.

In situations where you are using a simple `[IntentManaged(Mode.<mode>)]` attribute, you can use any of the following attributes:

- `[IntentFully]` (equivalent to `[IntentManaged(Mode.Fully)]`)
- `[IntentIgnore]` (equivalent to `[IntentManaged(Mode.Ignore)]`)
- `[IntentMerge]` (equivalent to `[IntentManaged(Mode.Merge)]`)

Additionally, the following attributes can be used to override particular [code management properties](#code-management-attribute-properties):

- `[IntentFullyAttributes]`
- `[IntentFullyBody]`
- `[IntentFullyComments]`
- `[IntentFullySignature]`
- `[IntentIgnoreAttributes]`
- `[IntentIgnoreBody]`
- `[IntentIgnoreComments]`
- `[IntentIgnoreSignature]`
- `[IntentMergeAttributes]`
- `[IntentMergeBody]`
- `[IntentMergeComments]`
- `[IntentMergeSignature]`

These attributes can also be combined, for example to have a method have its signature fully managed, but the rest of it ignored, you can combine them as follows:

```csharp
[IntentIgnore]
[IntentFullySignature]
public void ChangeCountry(string country)
{
    throw new NotImplementedException();
}
```

You can also combine the attributes into a single list, the following code is functionally identical to the previous example:

```csharp
[IntentIgnore, IntentFullySignature]
public void ChangeCountry(string country)
{
    throw new NotImplementedException();
}
```

### "Tag Mode" attributes

> [!NOTE]
> File level "Tag Mode" attributes were introduced in version `4.2.0` of the `Intent.OutputManager.RoslynWeaver` module, ensure you have at least this version of the module installed for them to be able to work.

These attributes manage the "Tag Mode" for the current file.

#### Explicit Tag Mode

- `[assembly: IntentTagMode(TagMode.Explicit)]`

  or

- `[assembly: IntentTagModeExplicit]`

The RoslynWeaver will only look at the existing file for code management attributes except in the case where the generated template output will add new _syntax nodes_ to the existing file.

#### Implicit Tag Mode

- `[assembly: IntentTagMode(TagMode.Implicit)]`

  or

- `[assembly: IntentTagModeImplicit]`

When a _syntax node_ has no code management attribute of its own, the RoslynWeaver will attempt to find the corresponding _syntax_ node in the template generated content and use its code management attribute instructions. If the RoslynWeaver sees that the existing file's _syntax node's_ code management attribute instructions are identical to that of the _syntax node_ in the generated template output, it will remove it from existing file. This mode is useful if you want to keep the amount of code management attributes in your files to an absolute minimum.

> [!TIP]
> If you would like to make "implicit tag mode" the default for all files, this can be done with the [tag mode application setting](#tag-mode).

### Block statement code management behaviour

Statements within code block _syntax nodes_ (e.g. method body, constructor body, delegate body, etc) can also support certain code management capabilities.

> [!NOTE]
> Support for management of statements was added in version `4.0.0` of the `Intent.OutputManager.RoslynWeaver` module, ensure you have at least this version of the module installed for them to be able to work.

#### Fully mode

You can add your own statements to a code block by adding a comment above with a code management instruction, for example:

```csharp
// Template generated content:
[IntentManaged(Mode.Fully)]
public void Method()
{
    var variable1 = "variable1";
}

// Content in your file, added after initial generation:
[IntentManaged(Mode.Fully)]
public void Method()
{
    var variable1 = "variable1";
    // IntentIgnore
    var myVariable = "myVariable";
}
```

With the above, even though the body of the method is "fully" managed, the `var myVariable = "myVariable";` will not be removed due to having `// IntentIgnore` above it.

This also works for statements which have statement blocks, with the above example you could have alternatively added an `if` statement:

```csharp
[IntentManaged(Mode.Fully)]
public void Method()
{
    var variable1 = "variable1";
    // IntentIgnore
    if (SomeCondition)
    {
        var myStatement1 = "myStatement1";
        var myStatement2 = "myStatement2";
    }
}
```

#### Merge mode

Inline with merge behaviour of other _syntax nodes_, the RoslynWeaver will add any statements which are on the template and missing from your file, it will remove any statements which are no longer being generated by the template and it will always leave code manually added by a user:

```csharp
// Template generated content:
[IntentManaged(Mode.Fully)]
public void Method()
{
    if (_flag)
    {
        // Do something
    }

    var variable1 = "variable1";
}

// Content in your file (will not be changed by the software factory):
[IntentManaged(Mode.Fully)]
public void Method()
{
    if (_flag)
    {
        // Do something
    }

    var variable1 = "variable1";
    var myVariable = "myVariable";
}
```

If at a later time, the template content changes to add and remove statements, then previously generated statements will be removed and new ones will be added, all without touching the statements which were manually added:

```csharp
// Template generated content:
[IntentManaged(Mode.Fully)]
public void Method()
{
    var variable1 = "variable1";

    for (var i = 1; i < 10; i++)
    {
        _counter++;
    }
}

// Content in your file before running the software factory:
[IntentManaged(Mode.Fully)]
public void Method()
{
    if (_flag)
    {
        // Do something
    }

    var variable1 = "variable1";
    var myVariable = "myVariable";
}

// Content in your file after running the software factory:
[IntentManaged(Mode.Fully)]
public void Method()
{
    var variable1 = "variable1";

    for (var i = 1; i < 10; i++)
    {
        _counter++;
    }

    var myVariable = "myVariable";
}
```

> [!NOTE]
> Prior to version 4.7.0 of the `Intent.OutputManager.RoslynWeaver` module, it was not possible for it to identify what was previously generated by Intent so it would never delete anything when in merge mode.

##### Updating variable values

Block statement merge mode also allows you to update variable values:

```csharp
// Template generated content:
[IntentManaged(Mode.Fully)]
public void Method()
{
    var variable1 = "variable1";
}

// Content in your file (will not be updated by the software factory):
[IntentManaged(Mode.Fully)]
public void Method()
{
    var variable1 = "my alternative value";
}
```

##### Updating other kinds statements

For other kinds of statements that you would like to update, you can use the `// [IntentFully(Match = "…")]` or `// [IntentIgnore(Match = "…")]` comments to specify how Intent Architect should know which statement to replace:

```csharp
// Template generated content:
[IntentManaged(Mode.Merge)]
public void Method()
{
    SomeOtherMethod(argument);
}

// Content in your file (will not be updated by the software factory):
[IntentManaged(Mode.Merge)]
public void Method()
{
    // [IntentIgnore(Match = "SomeOtherMethod")]
    SomeOtherMethod(argument, additionalArgument);
}
```

In the above example, the `SomeOtherMethod` value for the commented out attribute lets Intent know to correlate this statement in your existing file with the first statement in the template output starting with that string.

Template authors can also add this line to their templates which lets Intent know how to try correlate the template expression with that in the existing file. When `// [IntentFully(Match = "…")]` only exists on the template, it is not included in the template output.

##### Nested block statements

As with [fully mode](#fully-mode), if your statement was an if statement with a block statement, that would be retained too.

#### The `// IntentInitialGen` instruction

This instruction is useful for having a statement which can be initially generated by a template, and then changed or even removed by users without the Software Factory trying to update or put the it back into the file.

When `[IntentInitialGen]` is on a statement in a template, it is generated during the initial generation (creation) of a file and is then essentially treated as "Ignored" on subsequent generations. Furthermore, if the statement is deleted then it won't be re-generated on subsequent updates to the file.

During initial generation of a file, the instruction is removed from statement so this instruction will never be visible except to template authors.

Consider the below template content:

```csharp
[IntentFully, IntentMergeBody]
public int DoSomeCalculationFor(Guid id)
{
    // IntentInitialGen
    throw new NotImplementedException();
}
```

When the method is initially generated it inserts the the `throw new NotImplementedException();` statement but without the code management instruction:

```csharp
[IntentFully, IntentMergeBody]
public int DoSomeCalculationFor(Guid id)
{
    throw new NotImplementedException();
}
```

If the user deletes the statement while adding their own logic, Intent Architect will not try to bring it back, for example:

```csharp
[IntentFully, IntentMergeBody]
public int DoSomeCalculationFor(Guid id)
{
    return _calculationService.Calculate(id);
}
```

#### Method chains

In both fully and merge mode of a block statement, you can add to a chain to a method chain using `// IntentIgnore` above it, for example:

```csharp
void Method()
{
    Member
      .GeneratedChain1()
      // IntentIgnore
      .ManuallyAddedChain()
      .GeneratedChain2();
}
```

## Module Settings

![RoslynWeaver Settings](images/roslynweaver-settings.png)

The `Intent.OutputManager.RoslynWeaver` Module has the following settings which will instruct Intent Architect to behave in certain ways:

### Usings Sorting

This will instruct Intent Architect to order the `using directives` located above or within a `namespace` scope within a C# file.

| Option                                        | Description                                                                                                               |
|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
| None                                          | The order of the using directives will remain unchanged.                                                                  |
| Alphabetical                                  | The using directives will be sorted alphabetically in ascending order.                                                    |
| Alphabetical, place 'System' directives first | The using directives will be sorted alphabetically except it will give first priority to `System` based using directives. |

### Tag Mode

_Tag Mode_ can be used to control inclusion of `[IntentManaged(…)]` and `[DefaultIntentManaged(…)]` attributes in the output file.

| Option        | Description |
|---------------|-------------|
| Explicit      | The RoslynWeaver will only look at the existing file for `[IntentManaged(…)]` attributes except in the case where the generated template output will add new _syntax nodes_ to the existing file. |
| Implicit      | When a _syntax node_ has no `[IntentManaged(…)]` attribute of its own, the RoslynWeaver will attempt to find the corresponding _syntax_ node in the template generated content and use its `[IntentManaged(…)]` attribute instructions. If the RoslynWeaver sees that the existing file's _syntax node's_ `[IntentManaged(…)]` is identical to that of the _syntax node_ in the generated template output, it will remove it from existing file. This mode is useful if you want to keep the amount of `[IntentManaged(…)]` attributes in your files to an absolute minimum. |
| Template Only | Like with _Implicit_ mode, when a _syntax node_ has no `[IntentManaged(…)]` attribute of its own, the RoslynWeaver will attempt to find the corresponding _syntax_ node in the template generated content and use its `[IntentManaged(…)]` attribute instructions. After running the code management logic, **RoslynWeaver will remove all `[IntentManaged(…)]` and `[DefaultIntentManaged(…)]` attributes from the file**. This mode is useful if you want absolutely no `[IntentManaged(…)]` or `[IntentDefaultManaged(…)]` attributes in your code base. **WARNING: This mode removes all code management instructions from your code files, ensure you have a backup of your files (or have a commit in your source control management) in case you wish to rollback this change.** |

### Usings Placement

This will instruct Intent Architect where to place the `using` directives within a C# file.

| Option                   | Description                                                            |
|--------------------------|------------------------------------------------------------------------|
| Default                  | All using directives will be placed at the top of the C# file.         |
| Move to inside namespace | All using directives will be placed within the scope of a `namespace`. |

### Code Management in C# Project files

Intent Architect automatically manages NuGet packages and will install the minimum required version of a NuGet package to ensure that a module will function as expected and generate the correct code.

If additional NuGet packages are manually `added` to the csproj file, or a NuGet package is `upgraded` to a later version than Intent Architect is expecting, the references and versions will not be altered by the Software Factory execution.

There may be some use cases where Intent Architect will want to alter the referenced packages (such as `removing` unused references, or `upgrading` a package to the minimum required version), but you would like Intent Architect to ignore these changes.

The `IntentIgnore` attribute can be used in the csproj file to instruct Intent Architect to ignore the package reference. In the below snippet from a csproj file, the `IntentIgnore` attribute will prevent Intent Architect from removing or updating the version number of the `Microsoft.EntityFrameworkCore` NuGet package:

``` xml
<ItemGroup>
    <PackageReference IntentIgnore="true" Include="Microsoft.EntityFrameworkCore" Version="8.0.21" />
</ItemGroup>
```

## Frequently asked questions

### How can I disable the RoslynWeaver from formatting my C# files?

By default the RoslynWeaver will automatically format files under [code management](https://docs.intentarchitect.com/docs-md/application-development/code-management/about-code-management/about-code-management.md). If this is undesired you can disable this behaviour by using the `.WithAutoFormatting(...)` extension method with the first parameter set to `false` in the `DefineFileConfig` method of your template:

```csharp
protected override CSharpFileConfig DefineFileConfig()
{
    return new CSharpFileConfig(
        className: "MyClass",
        @namespace: OutputTarget.GetNamespace())
        .WithAutoFormatting(false);
}
```

### Why isn't the RoslynWeaver removing extraneous `using directives`?

By default RoslynWeaver uses `Merge` as the management mode for `using directives`, where it will never remove nodes unless they were previously generated by the software factory but aren't any more. This can be overridden by adding an `[assembly: DefaultIntentManaged(Mode.Fully, Targets = Targets.Usings)]` in your file, typically just beneath the existing `[DefaultIntentManaged(…)]` attribute, for example:

```csharp
[assembly: DefaultIntentManaged(Mode.Fully)]
[assembly: DefaultIntentManaged(Mode.Fully, Targets = Targets.Usings)]
```

### Why are are _class_ members (such as _methods_, _properties_, _fields_, etc) being overwritten by Intent even though the _class_ has `[IntentManaged(Mode.Merge)]` / `[IntentManaged(Mode.Fully, Body = Mode.Merge)]` on it?

Generally, the `IntentManaged` attribute [does not effect descendant _syntax nodes_](#intentmanaged-when-applied-to-type-declaration-syntax-nodes) (an exception being `[IntentManaged(Mode.Ignore)]`), it only applies to the _syntax node_ it's directly applied to (the class in this case), allowing you to "opt-out" of being fully managed.

When you do not specify the `Body` mode specifically for an `IntentManaged` attribute, then the all its properties (including `Body`) use the default constructor's mode. For _type declarations_ (e.g. _class_, _interface_, _enum_, _record_, etc), the `Body` mode is used to control whether or not members (i.e. methods, fields, properties, etc) are added/removed, this is what Intent Architect will do under the following `Body` modes:

- **Fully:** Members are added to/removed from the existing file to ensure they match the template output.
- **Merge:** Any members from the template output which are missing from the existing file will be added, additional members which were previously added by Intent will be removed and any additional members which where manually user added will not be removed.
- **Ignore:** No members will be added to or removed from the existing file.

### How does Intent know what was previously generated and is now no longer being generated?

After pressing Apply in the software factory, for all files managed by the software factory (except for files which are unchecked in the Changes view), the Software Factory will save the template output (i.e. the "pre-merge" output) for each file in the `.intent/previous_output` of the current Intent Architect application.

### Why didn't Intent automatically delete something which was no longer being generated even though it was in merge mode?

The `.intent` folder which [contains the previous template output](#how-does-intent-know-what-was-previously-generated-and-is-now-no-longer-being-generated) is [not committed to source control](https://docs.intentarchitect.com/docs-md/application-development/applications-and-solutions/git-and-scm-guidance/git-and-scm-guidance.md) so as to prevent these files causing noise in your SCM logs and possible pull requests. This means that if you have a fresh checkout of your source code, or for some reason you haven't applied any software changes on your machine prior to making an update which should delete something, the previous output may be missing or out of date (for example to due it last being run by a different user on a different machine), so it may not be aware of some things which were actually generated by Intent.
