Ivy.Analyser 1.2.44

dotnet add package Ivy.Analyser --version 1.2.44
                    
NuGet\Install-Package Ivy.Analyser -Version 1.2.44
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ivy.Analyser" Version="1.2.44">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ivy.Analyser" Version="1.2.44" />
                    
Directory.Packages.props
<PackageReference Include="Ivy.Analyser">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ivy.Analyser --version 1.2.44
                    
#r "nuget: Ivy.Analyser, 1.2.44"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ivy.Analyser@1.2.44
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ivy.Analyser&version=1.2.44
                    
Install as a Cake Addin
#tool nuget:?package=Ivy.Analyser&version=1.2.44
                    
Install as a Cake Tool

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.

IVYHOOK007 - Hook Called Inline in Expression (Warning)

Severity: Warning
Message: '{hookName}' should be assigned to a local variable at the top of the Build method, not called inline in an expression.
Description: Hooks must be assigned to a top-level local variable or called as a standalone expression statement. Do not call hooks inline within widget construction expressions, pipe chains, constructor arguments, or return statements.

Quick Fix

The analyzer includes a CodeFixProvider that can automatically extract inline hook calls to variables.

How to use:

  1. Place your cursor on the warning (yellow squiggle on the hook call)
  2. Trigger the quick action menu:
    • Visual Studio: Press Ctrl+. or click the lightbulb icon
    • VS Code: Press Ctrl+. or click the lightbulb icon
    • Rider: Press Alt+Enter or click the lightbulb icon
  3. Select "Extract hook to variable" from the menu
  4. The hook call will be moved to the top of the Build() method and assigned to a variable

Example:

// Before fix:
public override object Build()
{
    return new Text(UseState(0).Value.ToString());  // ⚠️ Warning IVYHOOK007
}

// After applying quick fix:
public override object Build()
{
    var state = UseState(0);  // ✅ Extracted
    return new Text(state.Value.ToString());
}

Note: The quick fix generates variable names automatically (UseState → state, UseEffect → effect, etc.). If a variable with that name already exists, it will append a number (state2, state3, etc.).

IVYAPP001 - App Missing Parameterless Constructor (Error)

Severity: Error
Message: App '{AppName}' must have a parameterless constructor, use UseService<T>() inside Build() instead of constructor injection.
Description: App classes are instantiated via Activator.CreateInstance and require a parameterless constructor. Use UseService<T>() inside Build() for dependency injection.

Quick Fix

The analyzer includes a CodeFixProvider that can automatically add a parameterless constructor.

How to use:

  1. Place your cursor on the error (red squiggle on the class name)
  2. Trigger the quick action menu:
    • Visual Studio: Press Ctrl+. or click the lightbulb/screwdriver icon
    • VS Code: Press Ctrl+. or click the lightbulb icon
    • Rider: Press Alt+Enter or click the lightbulb icon
  3. Select "Add parameterless constructor" from the menu
  4. An empty public ClassName() { } constructor will be added to your class

Example:

// Before fix:
[App]
public class MyApp  // ❌ Error IVYAPP001
{
    public MyApp(IConfigService config) { }
    public override object Build() => new Text("Hello");
}

// After applying quick fix:
[App]
public class MyApp  // ✅ Fixed
{
    public MyApp() { }  // Added automatically
    public MyApp(IConfigService config) { }
    public override object Build() => new Text("Hello");
}

Note: The quick fix adds an empty parameterless constructor. You'll need to manually update your code to use UseService<T>() inside the Build() method instead of constructor injection.

IVYSERVICE001 - UseService Should Use Interface (Warning)

Severity: Warning
Message: UseService<{ConcreteType}> should use interface I{ConcreteType} instead. Using concrete types breaks testability and violates dependency inversion.
Description: When calling UseService<T>(), always prefer interface types over concrete types when an interface is available. This ensures proper dependency injection, testability, and adherence to SOLID principles.

✅ Valid Usage
public override object? Build()
{
    var config = UseService<IConfigService>();     // ✅ Valid - using interface
    var job = UseService<IJobService>();           // ✅ Valid - using interface
    var git = UseService<IGitService>();           // ✅ Valid - using interface
    
    return new Button();
}
❌ Invalid Usage
public override object? Build()
{
    var config = UseService<ConfigService>();     // ⚠️ Warning IVYSERVICE001 - use IConfigService
    var job = UseService<JobService>();           // ⚠️ Warning IVYSERVICE001 - use IJobService
    
    return new Button();
}

Note: This warning only appears when a corresponding interface (prefixed with 'I') exists in the same namespace. If no interface exists, no warning is shown.

Quick Fix

The analyzer includes a CodeFixProvider that can automatically fix IVYSERVICE001 warnings with a single click.

How to use:

  1. Place your cursor on the warning (red/yellow squiggle)
  2. Trigger the quick action menu:
    • Visual Studio: Press Ctrl+. or click the lightbulb/screwdriver icon
    • VS Code: Press Ctrl+. or click the lightbulb icon
    • Rider: Press Alt+Enter or click the lightbulb icon
  3. Select "Use interface I{ConcreteType}" from the menu
  4. The concrete type will be automatically replaced with its interface

Example:

// Before fix:
var config = UseService<ConfigService>();  // ⚠️ Warning IVYSERVICE001

// After applying quick fix:
var config = UseService<IConfigService>(); // ✅ Fixed

Fix All: You can apply the fix to multiple violations at once using "Fix All" in Visual Studio:

  • Fix All in Document: Fixes all IVYSERVICE001 warnings in the current file
  • Fix All in Project: Fixes all IVYSERVICE001 warnings in the project
  • Fix All in Solution: Fixes all IVYSERVICE001 warnings in the solution

Note: The quick fix only appears when the corresponding interface (prefixed with 'I') exists in the same namespace. If no interface exists, the warning will still appear but no automatic fix will be offered.

Configuration

The analyzer runs automatically when you build your project. No additional configuration is needed.

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
#pragma warning disable IVYSERVICE001  // Suppress UseService interface 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
#pragma warning restore IVYSERVICE001

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.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

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.44 231 4/16/2026
1.2.43 233 4/16/2026
1.2.42 233 4/15/2026
1.2.42-pre-20260414163705 92 4/14/2026
1.2.40 344 4/14/2026
1.2.39-pre-20260414141311 79 4/14/2026
1.2.37-pre-20260414092333 81 4/14/2026
1.2.37-pre-20260414091731 75 4/14/2026
1.2.37-pre-20260414084831 89 4/14/2026
1.2.37-pre-20260414084740 80 4/14/2026
1.2.37-pre-20260412104447 187 4/12/2026
1.2.37-pre-20260410110521 85 4/10/2026
1.2.37-pre-20260410104611 90 4/10/2026
1.2.37-pre-20260409163352 80 4/9/2026
1.2.37-pre-20260408144108 87 4/8/2026
1.2.37-pre-20260408132826 78 4/8/2026
1.2.36 1,761 4/8/2026
1.2.36-pre-20260408100712 81 4/8/2026
1.2.36-pre-20260407134014 81 4/7/2026
1.2.35 987 4/6/2026
Loading failed