Ivy.Analyser
1.2.27
dotnet add package Ivy.Analyser --version 1.2.27
NuGet\Install-Package Ivy.Analyser -Version 1.2.27
<PackageReference Include="Ivy.Analyser" Version="1.2.27"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Ivy.Analyser" Version="1.2.27" />
<PackageReference Include="Ivy.Analyser"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Ivy.Analyser --version 1.2.27
#r "nuget: Ivy.Analyser, 1.2.27"
#:package Ivy.Analyser@1.2.27
#addin nuget:?package=Ivy.Analyser&version=1.2.27
#tool nuget:?package=Ivy.Analyser&version=1.2.27
Ivy.Analyser
A Roslyn-based .NET analyzer that enforces proper usage of Ivy framework hooks, similar to React's "Rules of Hooks".
Overview
This analyzer ensures that Ivy hook functions (such as UseState, UseEffect, etc.) are used only directly inside the Build() method of classes that inherit from ViewBase, following the same rules as React's Rules of Hooks. Violating these rules may cause runtime errors, so they are enforced at compile time.
The analyzer enforces that hooks must be called:
- ✅ At the top level of the
Build()method - ✅ Unconditionally (not inside if statements, loops, or switch statements)
- ✅ In the same order on every render
Installation
Using Package Manager Console
Install-Package Ivy.Analyser
Using .NET CLI
dotnet add package Ivy.Analyser
Using PackageReference
Add the following to your .csproj file:
<PackageReference Include="Ivy.Analyser" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Rules Enforced
✅ Valid Usage
Hook functions must be invoked directly inside the top level of the Build() method:
public class MyView : ViewBase
{
public override object? Build()
{
var state = UseState(false); // ✅ Valid
UseEffect(() => { /* ... */ }); // ✅ Valid
var memo = UseMemo(() => 42); // ✅ Valid
return new Button();
}
}
❌ Invalid Usage
The analyzer will report errors and warnings for these violations:
1. Hook calls inside lambdas (Error IVYHOOK001)
public override object? Build()
{
var handler = (Event<Button> e) =>
{
var s = UseState(false); // ❌ Error IVYHOOK001
};
return new Button().OnClick(handler);
}
2. Hook calls inside local functions (Error IVYHOOK001)
public override object? Build()
{
void LocalFunction()
{
var s = UseState(false); // ❌ Error IVYHOOK001
}
LocalFunction();
return new Button();
}
3. Hook calls in other methods (Error IVYHOOK001)
public override object? Build()
{
Initialize();
return new Button();
}
private void Initialize()
{
var s = UseState(false); // ❌ Error IVYHOOK001
}
4. Hook calls in anonymous methods (Error IVYHOOK001)
public override object? Build()
{
Action action = delegate()
{
var s = UseState(false); // ❌ Error IVYHOOK001
};
return new Button();
}
5. Hook calls conditionally (Warning IVYHOOK002)
public override object? Build()
{
if (someCondition)
{
var state = UseState(false); // ⚠️ Warning IVYHOOK002
}
var result = condition ? UseState(0) : UseState(1); // ⚠️ Warning IVYHOOK002 (ternary)
return new Button();
}
6. Hook calls in loops (Warning IVYHOOK003)
public override object? Build()
{
for (int i = 0; i < 10; i++)
{
var state = UseState(i); // ⚠️ Warning IVYHOOK003
}
foreach (var item in items)
{
var state = UseState(item); // ⚠️ Warning IVYHOOK003
}
while (condition)
{
var state = UseState(false); // ⚠️ Warning IVYHOOK003
}
return new Button();
}
7. Hook calls in switch statements (Warning IVYHOOK004)
public override object? Build()
{
switch (value)
{
case 1:
var state = UseState(false); // ⚠️ Warning IVYHOOK004
break;
}
return new Button();
}
8. Hook calls not at the top of Build() method (Warning IVYHOOK005)
public override object? Build()
{
var x = SomeMethod(); // Non-hook statement
var state = UseState(false); // ⚠️ Warning IVYHOOK005 - hook must be at the top
int y = 10; // Another non-hook statement
var state2 = UseState(0); // ⚠️ Warning IVYHOOK005
return new Button();
}
Hook Detection
The analyzer automatically detects hooks by their naming convention:
- Method name must start with
Use - The fourth character must be an uppercase letter
Examples:
- ✅
UseState,UseEffect,UseCustomHook,UseMyFeature - ❌
Use,Useless,useState,useEffect
This means any custom hooks you create following the UseX pattern will be automatically validated by the analyzer.
Diagnostic Details
IVYHOOK001 - Invalid Hook Usage (Error)
Severity: Error
Message: Ivy hook '{hookName}' can only be used directly inside the Build() method
Description: Hooks must be called directly inside the Build() method, not inside lambdas, local functions, or other methods.
IVYHOOK002 - Hook Called Conditionally (Warning)
Severity: Warning
Message: Ivy hook '{hookName}' cannot be called conditionally. Hooks must be called in the same order on every render.
Description: Hooks must be called unconditionally at the top level of the Build() method. Do not call hooks inside if statements, ternary operators, or other conditional logic.
IVYHOOK003 - Hook Called in Loop (Warning)
Severity: Warning
Message: Ivy hook '{hookName}' cannot be called inside a loop. Hooks must be called in the same order on every render.
Description: Hooks must be called unconditionally at the top level of the Build() method. Do not call hooks inside for, foreach, while, or do-while loops.
IVYHOOK004 - Hook Called in Switch Statement (Warning)
Severity: Warning
Message: Ivy hook '{hookName}' cannot be called inside a switch statement. Hooks must be called in the same order on every render.
Description: Hooks must be called unconditionally at the top level of the Build() method. Do not call hooks inside switch statements.
IVYHOOK005 - Hook Not at Top of Build Method (Warning)
Severity: Warning
Message: Ivy hook '{hookName}' must be called at the top of the Build() method, before any other statements.
Description: All hooks must be called at the very top of the Build() method, before any other non-hook statements. This ensures hooks are called in a consistent order on every render.
Configuration
The analyzer runs automatically when you build your project. No additional configuration is needed.
Suppressing Warnings (Not Recommended)
If you need to suppress the analyzer for specific cases, you can use:
#pragma warning disable IVYHOOK001 // Suppress error
#pragma warning disable IVYHOOK002 // Suppress conditional warning
#pragma warning disable IVYHOOK003 // Suppress loop warning
#pragma warning disable IVYHOOK004 // Suppress switch warning
#pragma warning disable IVYHOOK005 // Suppress not-at-top warning
var state = UseState(false); // This will not trigger the analyzer
#pragma warning restore IVYHOOK001
#pragma warning restore IVYHOOK002
#pragma warning restore IVYHOOK003
#pragma warning restore IVYHOOK004
#pragma warning restore IVYHOOK005
However, this is not recommended as it may lead to runtime errors.
IDE Integration
The analyzer works with:
- Visual Studio 2019/2022
- Visual Studio Code with C# extension
- JetBrains Rider
- Any IDE that supports Roslyn analyzers
Violations will be highlighted in your IDE with red squiggly lines and appear in the Error List.
Building from Source
git clone <repository-url>
cd Ivy.Analyser
dotnet build
dotnet test
dotnet pack
License
This project is licensed under the same license as the Ivy Framework.
Related
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.CSharp (>= 5.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.27 | 0 | 3/26/2026 |
| 1.2.26 | 0 | 3/26/2026 |
| 1.2.26-pre-20260326181340 | 0 | 3/26/2026 |
| 1.2.25 | 481 | 3/23/2026 |
| 1.2.25-pre-20260326173309 | 0 | 3/26/2026 |
| 1.2.25-pre-20260326162546 | 0 | 3/26/2026 |
| 1.2.25-pre-20260326160337 | 0 | 3/26/2026 |
| 1.2.23 | 775 | 3/20/2026 |
| 1.2.23-pre-20260323131453 | 77 | 3/23/2026 |
| 1.2.22 | 693 | 3/16/2026 |
| 1.2.22-pre-20260320124957 | 71 | 3/20/2026 |
| 1.2.21 | 171 | 3/16/2026 |
| 1.2.20 | 80 | 3/16/2026 |
| 1.2.19 | 220 | 3/15/2026 |
| 1.2.19-pre-20260316162707 | 79 | 3/16/2026 |
| 1.2.18 | 164 | 3/13/2026 |
| 1.2.18-pre-20260315131153 | 78 | 3/15/2026 |
| 1.2.17-pre-20260313203223 | 81 | 3/13/2026 |
| 1.2.17-pre-20260313100037 | 102 | 3/13/2026 |
| 1.2.17-pre-20260312131413 | 99 | 3/12/2026 |