Analyzer scope and rule set files
Control which parts of your code are subject to code analysis and customize diagnostic levels per-assembly.
Read time 7 minutesLast updated 10 days ago
By default, analyzers in the root of the folder apply to all the predefined assemblies in your project: that is, to any scripts in the folder or its subfolders that are not part of a custom assembly defined with an assembly definition file.
AssetsAssetsIf an analyzer is in a folder that contains an assembly definition file, or one of its subfolders, the analyzer only applies to that assembly, and to any other assembly that references it.
By using assembly definitions, for example, a package can supply analyzers that only analyze code related to the package, which can help package users to use the package API correctly.
Rule set files
You can further customize how code analyzer diagnostics are applied in different assemblies with a file. Rule sets allow you to configure the interpretation of analyzer rules per-assembly. For example, you can promote warnings to errors for a specific assembly. For more information on how to create a custom rule set, refer to Microsoft's Visual Studio documentation on how to create a custom rule set.
.rulesetDefault rule set
You can create a rule set file named in the root folder. The rules defined in apply to all predefined assemblies, and all assemblies that are built using assembly definition files.
Default.rulesetAssetsDefault.rulesetOverriding the default rule set
You can create additional rule set files for specific assemblies to override the default rule set.
To override the rules in for a predefined assembly, create a file in the root of the folder with the naming pattern . For example, the rules in apply to the code in .
Default.ruleset.rulesetAssets[PredefinedAssemblyName].rulesetAssembly-CSharp.rulesetAssembly-CSharp.dllOnly the following files are allowed inside the root folder:
.rulesetAssetsDefault.rulesetAssembly-CSharp.rulesetAssembly-CSharp-firstpass.rulesetAssembly-CSharp-Editor.rulesetAssembly-CSharp-Editor-firstpass.ruleset
To override the for a custom assembly defined with an assembly definition () file, create a dedicated rule set file and place it alongside the file. For example, might contain the rule set that overrides the default rule set for the assembly .
Default.ruleset.asmdef.asmdefAssets/Scripts/Runtime/MyRuntimeAssembly.rulesetAssets/Scripts/Runtime/MyRuntimeAssembly.asmdefRule set scope and best practices
The applies to all assemblies in the project, including predefined and custom assemblies, unless there are custom assembly-specific rule sets that override it. The is the only single rule set file that can apply to more than one assembly.
Default.rulesetDefault.rulesetAny additional custom files have a one-to-one relationship with assemblies. A custom file must be placed alongside the assembly definition () file for the assembly it applies to.
.ruleset.ruleset.asmdefIf you want the rule set to apply to all or most of the assemblies in your project, define your primary rule set in the and create additional files to exclude the other assemblies from it.
Default.ruleset.rulesetIf you want the rule set to apply to a minority of the assemblies in your project, make copies of your rule set next to each of the assemblies you want it to apply to.
Workflow: Test rule set files in Unity
To test rule set files in Unity, follow these steps:
Step 1: Set up the rule set file
-
Create a subfolder namedinside your project's
Subfolderfolder.Assets -
Inside:
Subfolder- Create a new assembly definition () file.
.asmdef - Save a duplicate copy of from the Install and use an existing analyzer or source generator page.
RethrowError.cs
- Create a new assembly definition (
-
Create afile inside
Default.rulesetwith the following code:Assets
<?xml version="1.0" encoding="utf-8"?><RuleSet Name="New Rule Set" Description=" " ToolsVersion="10.0"> <Rules AnalyzerId="ErrorProne.NET.CodeAnalyzers" RuleNamespace="ErrorProne.NET.CodeAnalyzers"> <Rule Id="ERP021" Action="Error" /> <Rule Id="EPC12" Action="None" /> </Rules></RuleSet>
The file defines the following rules:
Default.ruleset- Suppress , the warning about suspicious exception handling.
EPC12 - Elevate , the warning about incorrect exception propagation, to an error.
ERP021
Step 2: Reload the project
After you add the rule set files to your project, reimport any script that belongs to the assembly the rules apply to. This forces Unity to recompile the assembly using the new rule set files. After recompilation, two messages appear in the Console window:
Assets\Subfolder\RethrowError.cs(15,19): error ERP021: Incorrect exception propagation. Use throw; instead.Assets\RethrowError.cs(15,19): error ERP021: Incorrect exception propagation. Use throw; instead.Notice that Unity applies the rules defined in to both and .
Default.rulesetAssets/RethrowError.csAssets/Subfolder/RethrowError.csStep 3: Add a custom rule set
In , create a file, and give it any name you like (in this example ):
Assets/Subfolder.rulesetHello.ruleset<?xml version="1.0" encoding="utf-8"?><RuleSet Name="New Rule Set" Description=" " ToolsVersion="10.0"> <Rules AnalyzerId="ErrorProne.NET.CodeAnalyzers" RuleNamespace="ErrorProne.NET.CodeAnalyzers"> <Rule Id="ERP021" Action="Info" /> <Rule Id="EPC12" Action="Info" /> </Rules></RuleSet>
This new file tells Unity to print both and to the Console, without treating them as warnings or errors.
Hello.rulesetEPC12ERP021After Unity compiles the project again, the following messages appear in the Console window:
Assets\Subfolder\RethrowError.cs(14,23): info EPC12: Suspicious exception handling: only e.Message is observed in exception block.Assets\Subfolder\RethrowError.cs(15,19): info ERP021: Incorrect exception propagation. Use throw; instead.Assets\RethrowError.cs(15,19): error ERP021: Incorrect exception propagation. Use throw; instead.The rules in still apply to , but they no longer apply to , because the rules in override them.
Default.rulesetAssets\RethrowError.csAssets\Subfolder\RethrowError.csHello.rulesetFor more information on all the allowed rule set action files, refer to the Visual Studio documentation on Using the code analysis rule set editor.
Alternatives to rule set files
If you control the analyzer code, you can write the analyzer itself to behave differently based on particular locations or assemblies. For example, you might write the analyzer code to return without analyzing anything under to prevent it running on third party code.
Assets/ThirdPartyFor example, the following code snippet demonstrates how you might modify the example analyzer created in Create and use a Roslyn analyzer to return early if the code under analysis is in the or paths:
Assets/ThirdPartyAssets/Legacyprivate static void AnalyzeInvocation(SyntaxNodeAnalysisContext context){ var invocation = (InvocationExpressionSyntax)context.Node; if (!(invocation.Expression is MemberAccessExpressionSyntax memberAccess)) return; // Match calls where the method name is "Log" if (memberAccess.Name.Identifier.Text != "Log") return; // Verify the symbol belongs to UnityEngine.Debug var symbolInfo = context.SemanticModel.GetSymbolInfo(memberAccess); if (!(symbolInfo.Symbol is IMethodSymbol methodSymbol)) return; var containingType = methodSymbol.ContainingType; if (containingType?.ToDisplayString() != "UnityEngine.Debug") return; // Early out for exempt folders var location = invocation.GetLocation(); var tree = location.SourceTree; if (tree == null) return; var filePath = tree.FilePath ?? string.Empty; if (IsInExemptPath(filePath)) return; var diagnostic = Diagnostic.Create(Rule, memberAccess.GetLocation()); context.ReportDiagnostic(diagnostic);}private static bool IsInExemptPath(string filePath){ if (string.IsNullOrEmpty(filePath)) return false; var normalized = filePath.Replace('\\', '/'); return normalized.IndexOf("/Assets/Legacy/", System.StringComparison.OrdinalIgnoreCase) >= 0 || normalized.IndexOf("/Assets/ThirdParty/", System.StringComparison.OrdinalIgnoreCase) >= 0;}
Alternatively, you can use editorconfig file to centralize exclusions. For example, the following in the root of a project adjusts the warning created in the Create and use a Roslyn analyzer example to an error:
.editorconfigEX0001root = true[*.cs]# Set EX0001 to errordotnet_diagnostic.EX0001.severity = error